reactjs - tutorial - react-router-dom




كيفية الدفع إلى التاريخ في React Router v4؟ (13)

أبسط طريقة في React Router 4 هي الاستخدام

this.props.history.push('/new/url');

ولكن لاستخدام هذه الطريقة ، يجب أن يكون للمكون الموجود لديك حق الوصول إلى كائن history . يمكننا الحصول على طريق

  1. إذا كان المكون الخاص بك مرتبطًا Route مباشرة ، فسيكون المكون الخاص بك لديه حق الوصول إلى كائن history .

    على سبيل المثال:

    <Route path="/profile" component={ViewProfile}/>

    هنا ViewProfile لديه حق الوصول إلى history .

  2. إذا لم تكن متصلا Route مباشرة.

    على سبيل المثال:

    <Route path="/users" render={() => <ViewUsers/>}

    ثم يتعين علينا أن نستخدم مع withRouter ، وهو أمر ترتيب أعلى لتشويه المكون الحالي.

    داخل ViewUsers مكون

    • import { withRouter } from 'react-router-dom';

    • export default withRouter(ViewUsers);

    هذا كل شيء الآن ، مكوّن ViewUsers لديه حق الوصول إلى كائن history .

تحديث

2 - في هذا السيناريو ، قم بتمرير جميع props المسار إلى المكون الخاص بك ، ومن ثم يمكننا الوصول إلى this.props.history من المكون حتى بدون this.props.history

على سبيل المثال:

<Route path="/users" render={props => <ViewUsers {...props} />}

في الإصدار الحالي من React Router (v3) ، يمكنني قبول استجابة الخادم واستخدام browserHistory.push للانتقال إلى صفحة الاستجابة المناسبة. ومع ذلك ، لا يتوفر هذا الإصدار v4 ، ولست متأكدًا من الطريقة المناسبة للتعامل مع ذلك.

في هذا المثال ، باستخدام Redux ، تستدعي المكونات / app-product-form.js this.props.addProduct(props) عندما يرسل المستخدم النموذج. عندما يعود الخادم إلى النجاح ، يتم نقل المستخدم إلى صفحة السلة.

// 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؟


أقدم حلًا آخر في حال كان الأمر يستحق شخصًا آخر.

لدي ملف history.js حيث لدي ما يلي:

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

بعد ذلك ، على الجذر الخاص بي حيث يمكنني تحديد جهاز التوجيه الخاص بي ، استخدم ما يلي:

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 (
     <Provider store={store}>
      <Router history={history}>
       <Switch>
        ...
       </Switch>
      </Router>
     </Provider>
    )
   }
  }

أخيرًا ، على الإجراءات الخاصة بي actions.js يمكنني استيراد السجل والاستفادة من pushLater

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

بهذه الطريقة ، يمكنني الدفع إلى إجراءات جديدة بعد مكالمات API.

آمل أن يساعد!


إنشاء Router مخصص باستخدام browserHistory الخاص به:

import React from 'react';
import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';

export const history = createBrowserHistory();

const ExtBrowserRouter = ({children}) => (
  <Router history={history} >
  { children }
  </Router>
);

export default ExtBrowserRouter

بعد ذلك ، على الجذر الخاص بك حيث يمكنك تحديد Router الخاص بك ، استخدم ما يلي:

import React from 'react';       
import { /*BrowserRouter,*/ Route, Switch, Redirect } from 'react-router-dom';

//Use 'ExtBrowserRouter' instead of 'BrowserRouter'
import ExtBrowserRouter from './ExtBrowserRouter'; 
...

export default class Root extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <ExtBrowserRouter>
          <Switch>
            ...
            <Route path="/login" component={Login}  />
            ...
          </Switch>
        </ExtBrowserRouter>
      </Provider>
    )
  }
}

أخيرًا ، قم باستيراد history حيثما كنت في حاجة إليه واستخدمه:

import { history } from '../routers/ExtBrowserRouter';
...

export function logout(){
  clearTokens();      
  history.push('/login'); //WORKS AS EXPECTED!
  return Promise.reject('Refresh token has expired');
}

استخدام رد الاتصال. عملت معي!

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();
  });
}

في المكون ، عليك فقط إضافة رد الاتصال

this.props.addProduct(props, () => this.props.history.push('/cart'))

سؤال سيئ ، أخذني كثيرًا من الوقت ، لكن في النهاية ، لقد حللته بهذه الطريقة:

التفاف الحاوية الخاصة بك مع withRouter وتمرير التاريخ إلى عملك في mapDispatchToProps وظيفة. في العمل ، استخدم history.push ('/ url') للتنقل.

عمل:

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

حاوية:

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));

هذا صحيح بالنسبة لـ React Router v4.x.


في هذه الحالة ، تقوم بتمرير الدعائم إلى رانك. لذلك يمكنك ببساطة الاتصال

props.history.push('/cart')

إذا لم تكن هذه هي الحالة ، فلا يزال بإمكانك تمرير السجل من مكونك

export function addProduct(data, history) {
  return dispatch => {
    axios.post('/url', data).then((response) => {
      dispatch({ type: types.AUTH_USER })
      history.push('/cart')
    })
  }
}

هذا هو الاختراق الخاص بي (هذا هو ملف مستوى الجذر الخاص بي ، مع وجود القليل من عمليات إعادة التشغيل المختلطة هناك - على الرغم من أنني لا أستخدم react-router-redux ):

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

ReactDOM.render(
  <Provider store={store}>
    <Router history={customHistory}>
      <Route component={({history}) => {
        window.appHistory = history
        return (
          <App />
        )
      }}/>
    </Router>
  </Provider>,
  document.getElementById('root')
)

يمكنني بعد ذلك استخدام window.appHistory.push() أي مكان أريد (على سبيل المثال ، في وظائف متخزن / thunks / sagas الخاصة بي) ، كنت آمل أن أتمكن فقط من استخدام window.customHistory.push() ولكن لسبب ما react-router لم يظهر react-router مطلقًا في التحديث على الرغم من تغيير عنوان url. ولكن بهذه الطريقة ، لديّ استخدام react-router المثيل بالضبط. لا أحب وضع الأشياء في النطاق العالمي ، وهذا أحد الأشياء القليلة التي سأفعلها بها. لكنه أفضل من أي بديل آخر رأيته المنظمة البحرية الدولية.


هذه هي الطريقة التي فعلت بها:

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>
                <h1>Your Links</h1>
                <button onClick={this.onLogout}>Logout</button>
            </div>
        );
    }
}

استخدم this.props.history.push('/cart'); لإعادة التوجيه إلى صفحة السلة ، سيتم حفظها في كائن السجل.

استمتع ، مايكل.


وفقًا لراديو React Router v4 - جلسة Redux Deep Integration

التكامل العميق مطلوب من أجل:

"تكون قادرة على التنقل عن طريق إرسال الإجراءات"

ومع ذلك ، يوصون بهذا النهج كبديل عن "التكامل العميق":

"بدلاً من إرسال إجراءات للتنقل ، يمكنك تمرير كائن المحفوظات المقدم لتوجيه المكونات إلى تصرفاتك والتنقل معها هناك."

حتى تتمكن من لف المكون الخاص بك مع المكون ذو الترتيب العالي withRouter:

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

والتي سوف تمر API التاريخ إلى الدعائم. حتى تتمكن من استدعاء خالق التصرف الذي يمرر التاريخ كعلامة بارزة. على سبيل المثال ، داخل ReactComponent الخاص بك:

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

ثم ، داخل إجراءاتك / index.js:

export function actionCreatorName(history, param) {
  return dispatch => {
    dispatch({
      type: SOME_ACTION,
      payload: param.data
    });
    history.push("/path");
  };
}

يتيح React router V4 الآن استخدام سجل المحفوظات على النحو التالي:

this.props.history.push("/dummy",value)

يمكن الوصول إلى القيمة عندئذٍ أينما كان الموقع prop متاحًا كحالة state:{value} وليس حالة المكون.


يمكنك استخدام طرق history خارج مكوناتك. جرب بالطريقة التالية.

أولاً ، قم بإنشاء كائن history يستخدم حزمة المحفوظات :

// src/history.js

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

ثم ضعه في <Router> ( يرجى ملاحظة أنه يجب عليك استخدام import { Router } بدلاً من import { BrowserRouter as Router } ):

// src/index.jsx

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

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/login">Login</Link></li>
        </ul>
        <Route exact path="/" component={HomePage} />
        <Route path="/login" component={LoginPage} />
      </div>
    </Router>
  </Provider>,
  document.getElementById('root'),
);

تغيير موقعك الحالي من أي مكان ، على سبيل المثال:

// src/actions/userActionCreators.js

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

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

محدث : يمكنك أيضًا مشاهدة مثال مختلف قليلاً في الأسئلة المتداولة حول React Router .


يمكنك استخدامه مثل هذا كما أفعل ذلك لتسجيل الدخول وماني أشياء مختلفة

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</login>
    </div>

)

/*Step 1*/
myFunction(){  this.props.history.push("/home"); }
/**/
 <button onClick={()=>this.myFunction()} className={'btn btn-primary'}>Go 
 Home</button>






react-router-v4