我的ReactJS x Redux应用程序遇到了一个前所未有的奇怪问题,我很难弄清楚。
在我的ReactJS组件中,我正在连接一个动作创建者函数,该函数使用redux-thunk
进行异步调用,然后使用react-redux
中的connect()
函数+对象mapDispatchToProps
表示法将其调度到reducer。它看起来像这样:
const mapStateToProps = (state) => ({
...state.single_pano
});
const mapDispatchToProps = {
loadPano
};
export default connect(mapStateToProps, mapDispatchToProps)(PanoView);
为了简单起见,假设loadPano
动作创建者看起来像这样:
export const loadPano = (id) => {
console.log('Action creator called.');
return async (dispatch) => {
console.log('Dispatch function called.');
const doc = await db.doc('/path/to/doc/'+id).get();
dispatch({
type: 'LOAD_ACTION',
payload: doc
});
}
}
这是事情变得奇怪的地方:
在我的componentDidMount()
生命周期函数中,我对this.props.loadPano(panoID)
进行了一个调用,它完全按照预期工作(动作创建者中的两个console.log()
调用都被调用,async
/await
返回,并且动作被调度到reducer(。
稍后,我需要在组件的componentWillReceiveProps()
生命周期函数中再次调用this.props.loadPano(panoID)
,因为URL参数发生了更改,需要获取和重新加载一些数据但是,这次的结果是调用了动作创建者(loadPano
(,但从未调用过redux-thunk
调度函数(return (dispatch) => { ... }
(。我可以说是这样的,因为第一个console.log()
被调用了,但第二个从未被记录到控制台。
我正在做的其他不寻常的事情可能与此有关,但到目前为止,我还无法确认其中的任何一件:
PanoView
组件使用shouldComponentUpdate()
生命周期方法来控制何时渲染DOM- 我使用
PanoView
组件状态之外的变量来存储第三方库对象,该对象通过DOMref
直接修改DOM,但实际上无法与ReactJS一起正确使用,这有点麻烦/不是最佳实践。然而,我认为这是孤立的,看不出它会如何干扰Redux/Thunk。特别是因为调度函数第一次正确地启动
相关依赖项+版本(通过yarn
安装(:
"firebase": "^5.2.0",
"photo-sphere-viewer": "^3.4.0",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-redux": "^5.0.7",
"react-router-dom": "^4.3.1",
"redux": "^4.0.0",
"redux-thunk": "^2.3.0"
请求的更新:
我的PanoView
组件的componentWillReceiveProps
生命周期函数如下所示:
componentWillReceiveProps(newProps) {
// Pano received
const oldPanoID = this.props.match.params.panoID;
const newPanoID = newProps.match.params.panoID;
if (oldPanoID !== newPanoID) {
loadPano(newPanoID);
}
}
当我们对您的代码一无所知时,很难(几乎不可能(猜测问题出在哪里。你的componentWillReceiveProps
看起来怎么样?
这是一个可能会引起混乱的好做法:
const mapDispatchToProps = {
loadPano
};
Redux-thunk本质上是一个中间件,它检查每个调度的操作。如果操作返回一个函数,那么它调用该函数,然后将dispatch
和state
参数传递给返回的函数,然后它也调用该函数。
所以我的猜测是:
- 在
componendDidMount
中,您正在呼叫this.props.loadPano(id)
- 在
componentWillReceiveProps
中,您只调用loadPano
第一个是store.dispatch(loadPano)
,进入减速器。第二个只是loadPano
,并返回一个promise。(你的行动创造者(