[英]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');
}}
請注意,上述內容僅適用於
store
跟蹤位置更改。( 閱讀更多 ) react-router-4
在這種情況下,您將使用withRouter
包裝連接,這將使歷史對象在PostContainer
作為prop PostContainer
。 shouldComponentUpdate
編寫必要的邏輯。 如果以上聽起來像是一大堆亂碼,你可以隨時使用react-router-redux
的push
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.