React Router v4 da tarixga qanday urinasiz?

React router (v3) ning joriy versiyasida server javobini qabul qilib, tegishli javob sahifasiga o'tish uchun browserHistory.push dan foydalanishim mumkin. Biroq, bu v4 da mavjud emas va men bunga qanday mos kelish mumkinligini bilmayman.

Ushbu misolda, foydalanuvchi Redux-ni ishlatib, komponentlari/app-product-form.js foydalanuvchini forma yuborganida this.props.addProduct (props) ni chaqiradi. Server muvaffaqiyat qozonganida, foydalanuvchi Savat sahifasiga o'tiladi.

// actions/index.js
export function addProduct(props) {
  return dispatch =>
    axios.post(`${ROOT_URL}/cart`, props, config)
      .then(response => {
        dispatch({ type: types.AUTH_USER });
        localStorage.setItem('token', response.data.token);
        browserHistory.push('/cart');//no longer in React Router V4
      });
}

React Router v4 uchun funktsiyadan Savatga sahifasiga qanday yo'l-yo'riq berishim mumkin?

162
Iltimos, qabul qilingan javobni tanlang. Men sizga ovoz berar edim, lekin siz javobni qabul qilmaganingizdan beri uni to'xtatmoqchiman
qo'shib qo'ydi muallif Seth McClaine, manba
@Chris bu uchun echim topdingizmi? Men bu erda izohlaganingizdek, harakatdagi boshqa komponentga surish kerak
qo'shib qo'ydi muallif Mr.G, manba
Faqat GitHub-da React Router-ning masalalaridan taklif qilingan so'nggi echimdan va context dan foydalanib, siz qo'lda kerakli narsani topshirish uchun qo'shing "yo'q". Men kitob muallifi bo'lmasam, uni ishlatish kerak bo'lmaydi. Aslida, Facebook bunga qarshi taklif qiladi.
qo'shib qo'ydi muallif Chris, manba
@ Mr.G, afsuski, yo'q. Men o'qiganimdan so'ng React Router redux to'plami mavjud bo'lgan React Training komandasi bo'ldi. Men bu ishni bajarishga hech qanday imkoniyat qoldirmadim va ular buni hal qilish uchun ko'p ish bermadi.
qo'shib qo'ydi muallif Chris, manba

14 javoblar

React Router v4 v3 dan (va bundan oldin) umuman farq qiladi va foydalanganingiz kabi browserHistory.push() ni qilolmaysiz.

This discussion seems related if you want more info:

  • Creating a new browserHistory won't work because creates its own history instance, and listens for changes on that. So a different instance will change the url but not update the .
  • browserHistory is not exposed by react-router in v4, only in v2.

Aksincha, buni amalga oshirish uchun bir necha variant bor:

  • Use the withRouter high-order component

    Instead you should use the withRouter high order component, and wrap that to the component that will push to history. For example:

    import React from "react";
    import { withRouter } from "react-router-dom";
    
    class MyComponent extends React.Component {
      ...
      myFunction() {
        this.props.history.push("/some/Path");
      }
      ...
    }
    export default withRouter(MyComponent);
    

    Check out the official documentation for more info:

    You can get access to the history object’s properties and the closest 's match via the withRouter higher-order component. withRouter will re-render its component every time the route changes with the same props as render props: { match, location, history }.


  • Use the context API

    Using the context might be one of the easiest solutions, but being an experimental API it is unstable and unsupported. Use it only when everything else fails. Here's an example:

    import React from "react";
    import PropTypes from "prop-types";
    
    class MyComponent extends React.Component {
      static contextTypes = {
        router: PropTypes.object
      }
      constructor(props, context) {
         super(props, context);
      }
      ...
      myFunction() {
        this.context.router.history.push("/some/Path");
      }
      ...
    }
    

    Have a look at the official documentation on context:

    If you want your application to be stable, don't use context. It is an experimental API and it is likely to break in future releases of React.

    If you insist on using context despite these warnings, try to isolate your use of context to a small area and avoid using the context API directly when possible so that it's easier to upgrade when the API changes.

210
qo'shib qo'ydi
Nima uchun PropTypes.objectni ko'rsatish kerak? PropTypes faqat kelajakda ishlab chiquvchilar uchunmi?
qo'shib qo'ydi muallif Dog, manba
@Chris Ha, bu allaqachon yuqorida ko'rsatilgan. Siz buni qildingizmi?
qo'shib qo'ydi muallif Chris, manba
@SILENT to'g'ri. Bu mening javobimning pastki qismida. Shuning uchun nima uchun 2 ta usulni e'lon qildim;)
qo'shib qo'ydi muallif Chris, manba
Bu savolga javob bermaydi. Buning qaysi biriga tarixdan foydalanish mumkin? WithRouter yoki kontekstdan foydalanib, biror komponentdan tashqarida bo'lganida variantlar mavjud emas.
qo'shib qo'ydi muallif SunshinyDoyle, manba
@ Chris Haqiqatan ham, agar siz tarix ob'ektini kashf etmoqchi bo'lsangiz va uni o'zingiz ishlatsangiz, u urlni o'zgartiradi, lekin yuqorida aytib o'tilganidek, tarkibiy qismni yaratmaydi. Biroq, "history.push" komponentdan tashqaridan qanday foydalaniladi va majburiy komponentni ko'rsatish ham kerakmi?
qo'shib qo'ydi muallif cool, manba
Men ushbu mavzuni bir necha kun mobaynida o'rganib chiqdim va uni ishga sololmadim. Hatto yuqoridagi misolni ishlatib, men yo'riqnoma kontekstda aniqlanmayapman. Hozirda men reaktsiya v15.5.10, reaktsiya-router dom dom v4.1.1, prop-15.5.10 dan foydalanaman. Bu atrofdagi hujjatlar juda kam va juda aniq emas.
qo'shib qo'ydi muallif Stu, manba
Ha, men uni sinab ko'rdim. So'raganingiz uchun tashakkur. :-) Xo'sh, qanday qilib bu ish funktsiyasiga kontekstni olasiz? Hozircha bu aniqlanmagan.
qo'shib qo'ydi muallif Chris, manba
Rahmat. Buning uchun qanday echim kerakligini ko'rsatuvchi kod misoli bormi?
qo'shib qo'ydi muallif Chris, manba
Router bilan kodli misol juda foydali bo'ldi. rahmat.
qo'shib qo'ydi muallif geekymartian, manba
Uning sharmandasi React Routerda "reaktsiya" nomi bor. Odamlarni rasmiy routerni o'ylashiga olib keladi.
qo'shib qo'ydi muallif mmla, manba
Menimcha, Mixail Xorogjanskiyning fikri to'g'riligiga ishonaman, ayniqsa React komandasi barqarorlik nuqtai nazaridan kontekstni ishlatmaslik kerakligini aytadi.
qo'shib qo'ydi muallif SILENT, manba
@Stu buni bajarishi kerak this.context.router.history.push ('/ path');
qo'shib qo'ydi muallif Tushar Khatiwada, manba
Reakt 16.3 ga kelsak, kontekst API endi tajribali emas. React blog postasi React v16.3.0: Yangi hayot aylanishi va kontekst API haqida batafsil ma'lumot olish uchun .
qo'shib qo'ydi muallif Roy Scheffers, manba
WithRouter bilan ishlaydigan biznes mening yordamimda, rahmat.
qo'shib qo'ydi muallif azul, manba
context API endi React tomonidan rasmiy ravishda qo'llab-quvvatlanadi; hozir foydalanish xavfsizmi?
qo'shib qo'ydi muallif Mhmdrz_A, manba

Komponentlaringizdan tashqarida history usullarini ishlatishingiz mumkin. Quyidagi tarzda harakat qilib ko'ring.

Birinchidan tarixiy to'plami ishlatiladigan tarix obyektini yarating:

// src/history.js

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

Then wrap it in (please note, you should use import { Router } instead of import { BrowserRouter as Router }):

// src/index.jsx

// ...
import { Router, Route, Link } from 'react-router-dom';
import history from './history';

ReactDOM.render(
  
    
      <div>
        
  • <link to="/">Home</link>
  • <link to="/login">Login</link>
        
        
      </div>
    
  ,
  document.getElementById('root'),
);

Joriy manzilingizni har qanday joydan o'zgartiring, masalan:

// src/actions/userActionCreators.js

// ...
import history from '../history';

export function login(credentials) {
  return function (dispatch) {
    return loginRemotely(credentials)
      .then((response) => {
       //...
        history.push('/');
      });
  };
}

UPD: You can also see a slightly different example in React Router FAQ.

80
qo'shib qo'ydi
Bu savolga to'g'ri javob, thanks @OlegBelostotsky!
qo'shib qo'ydi muallif Ronald Rey, manba
@OlegBelostotskiy aytganidek, buni amalga oshirishga harakat qildim, lekin keyin history.push ("some path") dan keyin URL o'zgaradi, lekin sahifa o'zgarmaydi. Kodni ba'zi qismlarida ishlash uchun faqat window.location.reload() ni qo'yish kerak. Ammo, bir marta, men reduks davlat daraxtini saqlab qo'yishim kerak, va uni qayta tiklash uni yo'q qiladi. Boshqa har qanday echim?
qo'shib qo'ydi muallif sandddyyyy, manba
Qaydni qalinlashtirish uchun o'sha postni tahrir qilish imkoniyati bormi? IMO uni history bilan ishlash uchun eng muhim qismi
qo'shib qo'ydi muallif nehel, manba
@nehel, bajarildi.
qo'shib qo'ydi muallif Oleg Belostotsky, manba
@idunno withRouter yuqori darajadagi buyrug'ini ishlatib ko'ring.
qo'shib qo'ydi muallif Oleg Belostotsky, manba

Men shunday qildim:

import React, {Component} from 'react';

export default class Link extends Component {
    constructor(props) {
        super(props);
        this.onLogout = this.onLogout.bind(this);
    }
    onLogout() {
        this.props.history.push('/');
    }
    render() {
        return (
            <div>
                

Your Links

                <button onClick={this.onLogout}>Logout</button>
            </div>
        );
    }
}

Savat sahifasiga yo'naltirish uchun this.props.history.push ('/ cart'); so'zini tarix obyektida saqlanadi.

Enjoy, Maykl.

16
qo'shib qo'ydi
Bu savolga javob bermaydi. Buning qaysi biriga tarixdan foydalanish mumkin? Ushbu.props.history-dan foydalanib, biror komponentning tashqarisida bo'lgan vaqtni tanlash imkoniyati yo'q.
qo'shib qo'ydi muallif SunshinyDoyle, manba
Ha, bu juda yaxshi ishlay oladigan tarkibiy qismlarga o'xshaydi. Komponentdan tashqariga harakat qilishning yagona usuli qayta yo'naltirishga ega.
qo'shib qo'ydi muallif Chris, manba

React Router v4 hujjatiga - Redux Deep Integration sessiyasiga ko'ra

Mulohaza integratsiyaga quyidagilar kerak:

"dispetcherlik harakatlari bilan harakat qilish imkoniyatiga ega"

Biroq, bu yondashuvni "chuqur integratsiya" ga muqobil ravishda tavsiya qilamiz:

"Sizga harakat qilish uchun harakatlarni jo'natish o'rniga marshrut tarkibiy qismlariga taqdim etilgan tarix ob'ektini o'zingizning harakatlaringizga o'tkazishingiz va u bilan harakat qilishingiz mumkin."

Shunday qilib, siz komponentingizni Router yuqori buyurtma komponentiga ulashingiz mumkin:

export bilan default withRouter (ulash (null, {actionCreatorName}) (ReactComponent));

bu tarixiy rekordni API-ga o'tadi. Shunday qilib, siz tarixni param deb qabul qiladigan harakatni yaratuvchiga qo'ng'iroq qilishingiz mumkin. Misol uchun, ReactComponent ichida:

onClick={() => {
  this.props.actionCreatorName(
    this.props.history,
    otherParams
  );
}}

Keyin, sizning harakatlaringiz ichida/index.js:

export function actionCreatorName(history, param) {
  return dispatch => {
    dispatch({
      type: SOME_ACTION,
      payload: param.data
    });
    history.push("/path");
  };
}
13
qo'shib qo'ydi
RAHMAT. Bu ma'qullangan javobdan juda foydali bo'ldi.
qo'shib qo'ydi muallif johnbr, manba

Nasty savol, meni juda ko'p vaqt sarfladi, lekin oxir-oqibat, men buni shunday hal qildim:

Konteyneringizni withRouter bilan bilan o'rash va tarixni mapDispatchToProps funktsiyasiga o'tkazish. Amalga oshirish uchun history.push ('/ url') dan foydalaning.

Ro'yxatdan o'tish:

export function saveData(history, data) {
  fetch.post('/save', data)
     .then((response) => {
       ...
       history.push('/url');
     })
};

Idish:

import { withRouter } from 'react-router-dom';
...
const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    save: (data) => dispatch(saveData(ownProps.history, data))}
};
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Container));

Bu React router v4.x uchun amal qiladi.

11
qo'shib qo'ydi

this.context.history.push will not work.

Men shunga o'xshash ishlarni bajarishga muvaffaq bo'ldim:

static contextTypes = {
    router: PropTypes.object
}

handleSubmit(e) {
    e.preventDefault();

    if (this.props.auth.success) {
        this.context.router.history.push("/some/Path")
    }

}
6
qo'shib qo'ydi
Bu savolga javob bermaydi. Buning qaysi biriga tarixdan foydalanish mumkin? Ushbu context.extext yordamida komponentlar tashqarisida bo'lgan vaqt uchun imkoniyat emas.
qo'shib qo'ydi muallif SunshinyDoyle, manba
Rahmat - bu tushuntirish toza, aniq va aslida ishlaydi.
qo'shib qo'ydi muallif Po Rith, manba

Bu holatda siz o'zingizning tovoqqa proksi o'tmoqdasiz. Shuning uchun siz faqat qo'ng'iroq qilishingiz mumkin

props.history.push('/cart')

Agar shunday bo'lmasa, siz komponentdan tarixni hali ham uzata olasiz

export function addProduct(data, history) {
  return dispatch => {
    axios.post('/url', data).then((response) => {
      dispatch({ type: types.AUTH_USER })
      history.push('/cart')
    })
  }
}
4
qo'shib qo'ydi
Bu yaxshi yondashuvmi?
qo'shib qo'ydi muallif Jitin Maherchandani, manba

Agar boshqasiga layoqatli bo'lsam, yana bitta hal qilaman.

Menda quyidagilar mavjud bo'lgan history.js faylim bor:

import createHistory from 'history/createBrowserHistory'
const history = createHistory()
history.pushLater = (...args) => setImmediate(() => history.push(...args))
export default history

Keyinchalik, mening yo'riqnomamda routerimni belgilab qo'yganimda quyidagicha foydalanaman:

import history from '../history'
import { Provider } from 'react-redux'
import { Router, Route, Switch } from 'react-router-dom'

export default class Root extends React.Component {
  render() {
    return (
     
      
       
        ...
       
      
     
    )
   }
  }

Nihoyat, mening actions.js ustida Tarixni import va pushLater-dan foydalaning

import history from './history'
export const login = createAction(
...
history.pushLater({ pathname: PATH_REDIRECT_LOGIN })
...)

Shu tarzda, API chaqiruvlaridan so'ng yangi amallarni ishga solaman.

Umid qilamanki yordam beradi!

3
qo'shib qo'ydi

Buni bind() yordamida amalga oshirishga muvaffaq bo'ldim. index.jsx dagi tugmachani bosishni, serverga ba'zi ma'lumotlarni yuborishni, javobni baholashni va success.jsx manziliga yo'naltirishni xohladim. Mana buni qanday ishlashimga ...

index.jsx:

import React, { Component } from "react"
import { postData } from "../../scripts/request"

class Main extends Component {
    constructor(props) {
        super(props)
        this.handleClick = this.handleClick.bind(this)
        this.postData = postData.bind(this)
    }

    handleClick() {
        const data = {
            "first_name": "Test",
            "last_name": "Guy",
            "email": "[email protected]"
        }

        this.postData("person", data)
    }

    render() {
        return (
            <div className="Main">
                <button onClick={this.handleClick}>Test Post</button>
            </div>
        )
    }
}

export default Main

request.js:

import { post } from "./fetch"

export const postData = function(url, data) {
   //post is a fetch() in another script...
    post(url, data)
        .then((result) => {
            if (result.status === "ok") {
                this.props.history.push("/success")
            }
        })
}

success.jsx:

import React from "react"

const Success =() => {
    return (
        <div className="Success">
            Hey cool, got it.
        </div>
    )
}

export default Success

index.jsx -ga bu kodini postData </​​code> ga bog'lash orqali, this.props.history ga kirishga muvaffaq bo'ldim. request.js ... bu funksiyani turli qismlarga qayta ishlatishim mumkin, faqat this.postData = postData.bind (this) constructor() .

2
qo'shib qo'ydi

Redux dan foydalanayotgan bo'lsangiz, npm paketini reaktsiya-router-redux . Redux do'konidagi navigatsiya harakatlarini yuborish imkonini beradi.

Siz o'zingizni Readme'da tavsiflangan tarzda yaratishingiz lozim. fayl .

Eng qulay foydalanish usuli:

import { push } from 'react-router-redux'

this.props.dispatch(push('/second page'));

Konteyner/komponent bilan ikkinchi foydalanish usuli:

Idish:

import { connect } from 'react-redux';
import { push } from 'react-router-redux';

import Form from '../components/Form';

const mapDispatchToProps = dispatch => ({
  changeUrl: url => dispatch(push(url)),
});

export default connect(null, mapDispatchToProps)(Form);

Komponent:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class Form extends Component {
  handleClick =() => {
    this.props.changeUrl('/secondPage');
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}/>
      </div>Readme file
    );
  }
}
2
qo'shib qo'ydi
next versiyasini ishlatmaguningizcha, bu hozirda emas bilan reaktsiya-router-reduks bilan ishlaydi!
qo'shib qo'ydi muallif froginvasion, manba

Qayta qo'ng'iroqdan foydalaning. Men uchun ishladi!

export function addProduct(props, callback) {
  return dispatch =>
    axios.post(`${ROOT_URL}/cart`, props, config)
    .then(response => {
    dispatch({ type: types.AUTH_USER });
    localStorage.setItem('token', response.data.token);
    callback();
  });
}

Komponentda siz faqat qayta qo'ng'iroqni qo'shishingiz kerak

this.props.addProduct(props,() => this.props.history.push('/cart'))
2
qo'shib qo'ydi

Mana mening hackim (bu mening ildiz darajasidagi faylim, u erda biroz chalkashlik bilan aralashtirilgan bo'lsa-da, reaktsiya-router-redux foydalanmayman):

const store = configureStore()
const customHistory = createBrowserHistory({
  basename: config.urlBasename || ''
})

ReactDOM.render(
  
    
       {
        window.appHistory = history
        return (
          
        )
      }}/>
    
  ,
  document.getElementById('root')
)

Keyinchalik istagan joyga (masalan, redux do'kon vazifalari/thunks/sagas, va hokazo) window.appHistory.push() dan foydalanishi mumkin, men faqat window.customHistory .push() , lekin ba'zi bir sabablarga ko'ra, url o'zgargan bo'lsa ham, reaktsiya-router hech qachon yangilanmagan edi. Lekin bu bilan EXACT namunasi reaktsiya-router foydalanadi. Men butun dunyo bo'ylab narsalarni qo'yishni yoqtirmayman va bu men bilan qilgan narsalaridan biridir. Ammo bu IMOni ko'rgan boshqa variantlardan ko'ra yaxshiroqdir.

1
qo'shib qo'ydi

login va manny turli narsalar uchun buni amalga oshirish kabi uni ishlatishingiz mumkin

class Login extends Component {
  constructor(props){
    super(props);
    this.login=this.login.bind(this)
  }


  login(){
this.props.history.push('/dashboard');
  }


render() {

    return (

   <div>
    <button onClick={this.login}>login
    </div>

)
0
qo'shib qo'ydi
/*Step 1*/
myFunction(){  this.props.history.push("/home"); }
/**/
 <button onClick={()=>this.myFunction()} className={'btn btn-primary'}>Go 
 Home</button>
0
qo'shib qo'ydi
Ushbu kod javobni nima uchun va/yoki ushbu kodning qanday javob berishiga oid qo'shimcha kontekstni berib, uning uzoq muddatli qiymatini yaxshilashiga javob berishi mumkin.
qo'shib qo'ydi muallif rollstuhlfahrer, manba
Hech qanday importga ehtiyoj yo'q!
qo'shib qo'ydi muallif David Bagdasaryan, manba
ReactJS & ReactNative Uzbekistan
ReactJS & ReactNative Uzbekistan
81 ishtirokchilar

Guruh ReactJS va ReactNative bo'yicha muloqot qilish uchun ochilgan. Sizni qiziqtirsa: @nodejs_uz @react_uz @angular_uz @ngTashkent @yiiframework_uz @js_uzb @typescript_uzb @vuejs_uz @ngTashkent @laravel_uz @uzdevgroup Ish o'rinlari @UzDev_jobs