从 redux 更改状态后如何以及何时调用反应组件方法
Posted
技术标签:
【中文标题】从 redux 更改状态后如何以及何时调用反应组件方法【英文标题】:how and when to call a react component methods after state change from redux 【发布时间】:2016-11-28 20:51:02 【问题描述】:在单个反应组件中,用户单击按钮 => 调用方法 => 触发操作 => 异步获取 => 减速器更新状态 => 组件接收新道具。
回到触发我一直在使用的操作的原始组件:
componentWillReceiveProps(nextProps)
if(nextProps.someProp !== this.props.someProp)
//ok new prop is here
this.someMethod(nextProps.someProp);
我是否以正确的方式处理这件事?
它只是看起来有点笨拙,并且作为一种与用户操作或状态变化无关的回调机制。一旦有其中一些,它只会使遵循组件的逻辑流程变得更加困难,我有一个包含其中 3 个的组件,并且已经认为这并不容易推理,尤其是当它们是相关流程的一部分时 a > b > C 。我最终得到了这种东西:
componentWillReceiveProps(nextProps)
if(this.patchjavascriptWillLoad(nextProps))
this.createPatchInstance();
// method fires an action which will also result in state change that triggers the below.
if(this.patchInstanceWillBeReady(nextProps))
this.startPatchAudio(nextProps.webAudioPatch.instance);
// method fires an action which will also result in state change that triggers the below.
if(this.patchParametersWillChange(nextProps))
this.updateWebAudioPatchParameters(nextProps.webAudioPatchParameters);
// abstracted away if conditions to make componentWillReceiveProps more readable.
但这是应该如何完成的,还是没有将足够的逻辑传递给动作创建者的症状?
【问题讨论】:
不知道你的函数的细节很难判断,但感觉你的回调逻辑可以转移到动作创建者,特别是如果你使用 redux-thunk。 componentWillReceiveProps 正在被弃用。查找 getDerivedStateFromProps 【参考方案1】:多年后回到我自己的问题。
如果我可以使用功能组件,我会使用 react 钩子 useEffect。如果可以将逻辑外部化,那么也许是传奇。
useEffect(() =>
methodToCallIfPropChanges()
, [watchedProp]);
【讨论】:
【参考方案2】:更详细的示例会很有用,但根据您在这里的内容,我想我明白您的意思了。
简短回答:是的,这是没有将足够的逻辑传递给动作创建者的症状。理想情况下,您的组件应该是纯视图组件。在大多数情况下不需要componentWillReceiveProps
- 你只需渲染任何道具,就是这样。这就是 Abramov(redux 的创建者)主张功能组件的原因。更多关于 here.
如果您需要在异步调用返回一些数据后执行其他操作,如您所说,您可以在操作创建器中执行此操作。我将举一个使用 thunk 的示例:
编辑:我添加了一个组件示例,该组件将音频播放器的引用作为操作的参数传递。这样,操作就可以在异步步骤之后进行操作。
//An async action creator that uses the thunk pattern.
//You could call this method from your component just like any other
//action creator.
export function getMaDatums(audioPlayer, audioContext)
return function (dispatch)
//make the actual call to get the data
return fetch(`http://<your stuff here>`)
.then(data =>
//call dispatch again to do stuff with the data
dispatch(gotDataAction(data));
//call dispatch some more to take further actions
dispatch(...);
//since the component passed us references to these, we can
//interact with them here, after our data has loaded! FTW!
audioPlayer.doTheThings();
audiosession.doTheOtherThings();
//plus anything else you want...
);
如果您想了解有关使用 redux 执行异步操作的更多信息,或者就此而言,如何与您的 redux 应用程序中的有状态库进行交互,我强烈建议您阅读 redux 文档。上面的thunk示例的基础来自here。
祝你好运,享受 React + Redux 的乐趣!
【讨论】:
@Ian 谢谢,是的,我已经在使用 redux-thunk,我想问题是组件需要在操作之间与 dom api 通信。在我的情况下,这是使用与组件中的 dom Audio 元素相关联的网络音频 api。然后我需要能够将音频上下文作为单例传递。我可以理解表示组件中功能组件的论点,但我不确定如何在高阶组件/智能/容器中实现这一点。 @njorlsaga 在这种情况下,我会考虑将您的音频播放器的引用作为参数传递给操作。至于将音频上下文作为单例传递,如果您也将其作为参数传递给适当的操作,您也许可以围绕它进行设计。我编辑了答案以进行演示 - 这对您有帮助吗? @Ian,谢谢,是的,棘手的事情是音频上下文需要保存在某个地方作为参考,因为它在不同时间被其他事物调用(断开连接 - 重新连接,来源等)。 ),目前我将它存储在 redux 状态,但感觉有点脏,因为我确信引用不是不可变的。但是感谢您的帮助,它证实了我的一些怀疑,希望我可以将 componentWillReceiveProps 中的一些调用重构为动作创建者。 @njorlsaga:很高兴为您提供帮助,也很高兴这对您有用。也许您可以有一个启动动作,在动作中传递音频上下文,然后有一个中间件来监听该动作并保存对上下文的本地引用。然后中间件可以侦听其他操作(来自应用程序中的任何位置)并对上下文执行必要的操作。这样你就可以从状态树中获取音频上下文,并且仍然有一个单独的引用。 @Ian 啊,这很有趣我还没有编写任何中间件,也没有考虑过,只使用了像 redux-thunk 这样的第 3 方,我会检查一下。我需要在这方面做更多的研究,以了解在 react-redux 生态系统中存储引用或与此类实例(如 navigator.getUserMedia 等)交互的约定是什么。【参考方案3】:更新可能是由 props 或 state 的更改引起的。在重新渲染组件时,这些方法按以下顺序调用:
静态 getDerivedStateFromProps() shouldComponentUpdate() 渲染() getSnapshotBeforeUpdate() componentDidUpdate() 尝试使用 componentDidUpdate()反应文档https://reactjs.org/docs/react-component.html#updating
【讨论】:
以上是关于从 redux 更改状态后如何以及何时调用反应组件方法的主要内容,如果未能解决你的问题,请参考以下文章
使用 get API 调用反应全局状态/道具(没有 Redux)