簡體   English   中英

Redux & React Router:結合調度和導航(history.push)

[英]Redux & React Router: Combing dispatch and navigation (history.push)

我對如何在Redux使用 React Router 的history.push('/route')有點無能為力。

換句話說,如果你用 Redux 的mapDispatchToProps連接一個組件,你如何放置history.push('/route') ,它應該在調度某個動作后被觸發?

為了澄清這個問題,這是我的實驗片段......

class PostContainer extends React.Component {

    handleSubmit(data) {
        return this.props.addPost(data);
    }

    render() {
        return (<Post onSubmit={data=> this.handleSubmit(data)}/>);
    }
}

const mapDispatchToProps = (dispatch) => {
    return {    
        addPost: (data) => {
            dispatch(addPost(data)).data.then((result) => {
                dispatch(addPostFulfilled(result.data));

                //How do you call the following function?
                this.props.history.push('/posts')
            }).catch((error) => {
                dispatch(addPostRejected());
            });
        },      
    }
}

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

如您所見,只要通過addPostFulfilled將帖子添加到 Redux 的狀態,頁面就需要通過 history.push 移動到/posts

根據 Redux 的文檔,容器用於更新狀態(以及獲取數據)。 因此,愚蠢的組件不應該放置諸如history.push東西。

有什么比上面的代碼更好的方法?

任何建議將被認真考慮。

您可以使用用戶react-router-redux(需要初始設置)並從操作創建者發送您的操作

import { push } from 'react-router-redux'
class PostContainer extends React.Component {

  handleSubmit(data) {
    return this.props.addPost(data);
  }

  render() {
    return (
      <div>
        <Post onSubmit={data=> this.handleSubmit(data)}/>
      </div>
    );
  }
}

const mapDispatchToProps = (dispatch) => {
  return {    
    addPost: (data) => {
      dispatch(addPost(data)).data.then((result) => {
        dispatch(addPostFulfilled(result.data));

        //How do you call the following function?
        dispatch(push('/posts'));
      }).catch((error) => {
        dispatch(addPostRejected());
      });
    },      
  }
}
export default connect(null, mapDispatchToProps)(PostContainer);

或者只是將推送作為“完成回調”。

class PostContainer extends React.Component {

  handleSubmit(data, done) {
    return this.props.addPost(data, done);
  }

  render() {
    const { push } = this.props.history;
    return (
      <div>
        <Post onSubmit={data=> this.handleSubmit(data, push)}/>
      </div>
    );
  }
}

const mapDispatchToProps = (dispatch) => {
  return {    
    addPost: (data, done) => {
      dispatch(addPost(data)).data.then((result) => {
        dispatch(addPostFulfilled(result.data));

        //How do you call the following function?
        done('/posts')
      }).catch((error) => {
        dispatch(addPostRejected());
      });
    },      
  }
}

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

恕我直言,你甚至可以從愚蠢的組件中做一個history.push ,即

const mapDispatchToProps = (dispatch) => {
    return {    
        addPost: (data) => {
            dispatch(addPost(data)).data.then((result) => {
                dispatch(addPostFulfilled(result.data));
                <!-- removed from here -->
            }).catch((error) => {
                dispatch(addPostRejected());
            });
        },      
    }
}

完成addPostFulFilled數據后,您可以選擇在組件本身中執行this.history.push('/route') 您可以執行任何在props更新時調用的生命周期方法。 也許,將它添加到componentWillReceiveProps

class PostContainer extends React.Component {
  componentWillReceiveProps(nextProps){
  /*Added here*/
  if(nextProps.someFlag){ this.props.history.push('/someRoute');
}}

請注意,上述內容僅適用於

  1. 您可以通過store跟蹤位置更改。( 閱讀更多
  2. 您正在使用react-router-4在這種情況下,您將使用withRouter包裝連接,這將使歷史對象在PostContainer作為prop PostContainer
  3. 應注意防止不必要的重新渲染並在shouldComponentUpdate編寫必要的邏輯。

如果以上聽起來像是一大堆亂碼,你可以隨時使用react-router-reduxpush API,它可以在瀏覽器歷史記錄中推送新條目。 您可以在您選擇的任何地方導入,只需推送新路線即可。

可以在react-router-redux github頁面中看到詳細信息並引用文檔

push和replace都包含一個位置描述符,它可以是描述URL的對象或純字符串URL。 這些動作創建器也可以在一個對象中作為routerActions使用,在使用Redux的bindActionCreators()時可以方便地使用它們。

因此,直接在mapDispatchToProps中使用history.push() ,或者將它們作為要在PostContainer反應組件中使用的prop傳遞。


更簡潔的方法可能是使用React Router的<Redirect>

class PostContainer extends React.Component {
  render() {
    if (userJustAddedAPostRightNow === true) {
      return <Redirect to='/posts' />
    }
    return (
      <div>
        <Post onSubmit={addPost}/>
      </div>
    );
  }
}
export default connect(null, { addPost })(PostContainer);

如果成功, addPost將觸發狀態更改。 它應該將userJustAddedAPostRightNow更改為true,以便您將被重定向到帖子的頁面。

為了避免所有這些嵌套回調,您可以遵循Nir Kaufman的方法並處理中間件中的邏輯:

//src/middlewares/post.js
export const newPost = ({dispatch}) => next => action => {
  next(action);

  if (action.type === ADD_POST) {
    dispatch(apiRequest('POST', action.URL, null, ADD_POST_SUCCESS, ADD_POST_ERROR));
    dispatch(showSpinner());
  }
};

然后,成功時, ADD_POST_SUCCESS操作將通過reducer更改userJustAddedAPostRightNow的值。

在我的情況下, history.push()不能直接工作,

所以我找到了一個替代方案,我們應該通過window.location.reload();重新加載窗口window.location.reload();

它對我有用!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM