next.js mapStateToProps, mapDispatchToProps and getInitialProps
我目前仍在尝试使用next.js时围绕redux缠绕我的头,我不确定在next上使用redux的最佳方法是什么。我习惯于将mapDispatchToProps用于动作,将mapStateToProps用于道具。经过一番研究后,我现在在_app.js中使用推荐的next-redux-wrapper,但现在我正在与如何最好地获取道具和调度动作进行斗争。我查看了一些示例和实践,现在有一个基于这些示例之一的计数器组件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | class Counter extends Component { increment = () => { const {dispatch} = this.props dispatch(incrementCount()) } decrement = () => { const {dispatch} = this.props dispatch(decrementCount()) } reset = () => { const {dispatch} = this.props dispatch(resetCount()) } render () { const { count } = this.props return ( Count: <span>{count}</span> <button onClick={this.increment}>+1</button> <button onClick={this.decrement}>-1</button> <button onClick={this.reset}>Reset</button> ) } } function mapStateToProps (state) { const {count} = state.counter; return {count}; } export default connect(mapStateToProps)(Counter) |
到目前为止,我看到的大多数示例都执行与此操作类似的操作,或者仅在getInitialProps中调度操作。有理由这样做而不使用mapDispatchToProps吗?
导致此工作也很好:
1 | export default connect(null, {authenticate})(Signin); |
在getIntialProps中分派动作似乎有一些缺点(或者我犯了一些错误),导致在更改道具时不会再次执行它们。在我的用户配置文件组件中,我基于来自redux存储的令牌获取当前用户,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | const Whoami = ({isAuthenticated, user}) => ( <Layout title="Who Am I"> {(isAuthenticated && user && <h3 className="title is-3">You are logged in as {user}.) || <h3 className="title is-3 has-text-danger">You are not authenticated.} </Layout> ); Whoami.getInitialProps = async function (ctx) { initialize(ctx); const token = ctx.store.getState().auth.token; if(token) { const response = await axios.get(`${API}/user`, {headers: { authorization: token }}); const user = response.data.user; return { user }; } } const mapStateToProps = (state) => ( {isAuthenticated: !!state.auth.token} ); export default connect(mapStateToProps)(Whoami); |
这对于初始页面加载或在其中导航一个客户端来说非常完美,但是当令牌过期或我注销时,如果没有重新加载或没有mapStateToProps再次导航到该页面,页面将无法反映出来。但是将关注点拆分为2个单独的功能似乎很笨拙。但是我找不到更干净的方法来做到这一点。
提前致谢
关于
最好使用
关于
这个答案可能会有所帮助:
GetInitialProps: is provided by Next.js and it is NOT always triggered, so be careful with that, it happen when you wrap 1 component inside another. If the parent Component has GetInitialProps, the child's GetInitialProps will never be triggered, see this thread for more info.
在玩了更多之后,我发现了我问题的一些答案。 对于初始加载后数据不会更改的页面,我可以通过重写一下代码以返回分派来摆脱mapStateToProps,而仅使用getInitialProps,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | export function fetchShow(id) { return (dispatch) => { dispatch({ type: actionTypes.FETCH_SHOW_REQUESTED,id}); // we need to return the fetch so we can await it return fetch(`http://api.tvmaze.com/shows/${id}`) .then((response) => { if (!response.ok) { throw Error(response.statusText); } //dispatch(itemsIsLoading(false)); return response; }) .then((response) => response.json()) .then((data) => dispatch({type: actionTypes.FETCH_SHOW_SUCEEDED,id, show: data, time: Date.now() })) .catch(() => dispatch({ type: actionTypes.FETCH_SHOW_ERROR,id })); }; } Post.getInitialProps = async function ({store, isServer, pathname, query}) { const { id } = query; const {show} = await store.dispatch(fetchShow(id)); return {show}; } |
对于尚应根据存储更改来更新数据的页面,我不 我目前的想法是尝试编写一个可以从getInitialProps和mapStateToProps调用的帮助程序函数,以减少代码重复,但是我不