目前,我在使用next.js时仍在尝试围绕redux进行操作,我不确定在next上使用redux的最佳方法是什么。我习惯将mapDispatchToProps用于动作,将mapStateToProps用于道具。经过一番研究后,我现在在_app.js中使用推荐的next-redux-wrapper,但现在我正在与如何最好地获取道具和调度动作进行斗争。我查看了一些示例和实践,现在有一个基于这些示例之一的计数器组件。
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 (
<div>
<h1>Count: <span>{count}</span></h1>
<button onClick={this.increment}>+1</button>
<button onClick={this.decrement}>-1</button>
<button onClick={this.reset}>Reset</button>
</div>
)
}
}
function mapStateToProps (state) {
const {count} = state.counter;
return {count};
}
export default connect(mapStateToProps)(Counter)
到目前为止,我看到的大多数示例都执行与此操作类似的操作,或者仅在getInitialProps中调度操作。有理由这样做而不使用mapDispatchToProps吗?
同时也可以很好地完成此工作:
export default connect(null, {authenticate})(Signin);
在getIntialProps中调度动作似乎有一些缺点(或者我犯了一些错误),因为当props更改时,它们不会再次执行。在我的用户个人资料组件中,我基于来自redux存储的令牌获取当前用户,如下所示:
const Whoami = ({isAuthenticated, user}) => (
<Layout title="Who Am I">
{(isAuthenticated && user && <h3 className="title is-3">You are logged in as <strong className="is-size-2 has-text-primary">{user}</strong>.</h3>) ||
<h3 className="title is-3 has-text-danger ">You are not authenticated.</h3>}
</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个单独的功能似乎很笨拙。但是我找不到更干净的方法。
预先感谢
答案 0 :(得分:2)
关于mapDispatchToProps
:
最好使用this.props.dispatch
,至少因为它更易于测试:您可以将模拟函数传递给组件。使用getInitialProps
分派一些导入的动作可能会更加困难。
关于/var/log/sawtooth/
:
This answer可能会有所帮助:
GetInitialProps:由Next.js提供,它并不总是被触发,因此要小心,将1个组件包装在另一个组件中时会发生。如果父组件具有GetInitialProps,则永远不会触发子级的GetInitialProps,有关详细信息,请参见this thread。
答案 1 :(得分:1)
在与下一小节玩耍之后,我找到了问题的一些答案。对于初始加载后数据不会更改的页面,我可以通过重写一下代码以返回分派而摆脱mapStateToProps,而仅使用getInitialProps这样:
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调用的辅助函数,以减少代码重复,但是我不确定。