【问题标题】:how and when to call a react component methods after state change from redux从 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

标签: reactjs redux react-redux redux-thunk


【解决方案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

    【讨论】:

      猜你喜欢
      • 2018-05-21
      • 1970-01-01
      • 2021-05-12
      • 2022-10-25
      • 2019-04-29
      • 2016-05-17
      • 2019-03-08
      • 2020-10-12
      • 1970-01-01
      相关资源
      最近更新 更多