我有一个React组件,它在其componentWillMount
函数中调度redux状态更改.原因是当组件被加载时,它需要id
从url(powered by react-router
)获取,并触发一个用该id
数据设置状态的动作.
这是组件:
class Editor extends React.Component { componentWillMount() { const { dispatch, params } = this.props dispatch(editItem(params.id)) } render() { const item = this.props.item console.log("Editing", item) } } export default connect(state => ({item: state.item}))(Editor)
这是捕获:render
被叫两次.item
在第一次调用时未定义,在第二次调用时有效.理想情况下,只应在this.props.item
实际存在之后调用它(在editItem
调度和运行操作之后).
根据React文档:"如果你setState
在这个方法中调用,render()
将会看到更新的状态,并且只会在状态发生变化时执行一次."
在redux中,dispatch
相当于调用setState
,因为它会导致状态改变.但是,我猜测connect
工作仍然导致render
被调用两次.
有没有办法解决这个问题,除了添加像这样的线路if (!item) return;
?
您可能要做的一件事是创建一个更高阶的组件,它处理加载所需道具之前加载不同组件(或没有组件)的基本模式.
export const LoaderWrapper = function(hasLoaded, Component, LoaderComponent, onLoad) { return props => { if (hasLoaded(props)) { return} else { if (onLoad) onLoad(props) return { LoaderComponent ? : null } } } }
然后,您可以在连接组件之前将其包装起来以获得所需的行为.
export default connect(state => ({item: state.item}))(LoaderWrapper( ((props) => !!props.item), Editor, null, (props) => props.dispatch(editItem(props.params.id)) ))
您可能希望添加一些currying魔法,以确保您可以更好地组合这些类型的包装函数.请查看重新组合以获取更多信息.