【问题标题】:How to wait for a Redux action to change state from a React component如何等待 Redux 操作从 React 组件更改状态
【发布时间】:2018-04-19 01:10:41
【问题描述】:

我在一个组件中,该组件有一个 prop currentLineIndex 由其父容器传递并来自 Redux 减速器。

在同一个组件的函数中,我使用动作创建者更新currentLineIndex,然后我想滚动到新的currentLineIndex。但它还没有更新,所以我滚动到同一行。

我尝试过使用 async / await,如您所见,但它不起作用。

在我的组件中:

const { currentLineIndex, setCurrentLineIndex } = props; // passed by the parent container 

const handlePlaybackEnd = async () => {
  const nextIndex = currentLineIndex + 1;
  // await don't wait until global state / component props gets updated
  await setCurrentLineIndex(nextLineIndex);
  // so when I scroll on next line, I scroll to the same line.
  scrollToCurrentLine(); 
};

const scrollToCurrentLine = () => {
  const currentLineEl = document.getElementById(currentLineIndex);
  currentLineEl.scrollIntoView({ block: 'start', behaviour: 'smooth' });
};

actions/index.js

export function setCurrentLineIndex(index) {
  return { type: SET_CURRENT_LINE_INDEX, payload: index };
}

在我的减速器中:

case SET_CURRENT_LINE_INDEX:
  return {
    ...state,
    currentLineIndex: action.payload,
  };

Action 和 reducer 运行良好,我的组件状态已成功更新,但为时已晚。

我真的需要依赖 Redux 状态,而不仅仅是将 currentLineIndex 传递给 scrollToCurrentLine(),那太容易了:)

等到我的组件状态更新后,最好的解决方案是什么?

【问题讨论】:

  • 可以传入当前行索引吗? scrollToCurrentLine(nextIndex)?await 不适用于同步函数。
  • 我认为发生的事情是因为您将初始 prop.currentLineIndex 传递给 scrollToCurrentLine(),它正在使用该初始值。所以我认为你需要做的是使用componentWillReceiveProps() 并在setCurrentLineIndex() 更新后传递prop.currentLineIndex 的新值
  • 如果你的组件连接到redux状态,你应该什么都不用做,等redux更新状态,你的组件应该会自己刷新。

标签: javascript reactjs redux async-await


【解决方案1】:

我终于通过将我的组件设为类组件来解决这个问题,这样我就可以使用componentDidUpdate

componentDidUpdate(prevProps) {
  if (prevProps.currentLineIndex !== this.props.currentLineIndex) {
    this.scrollToCurrentLine(this.props.currentLineIndex);
  }
}

handlePlaybackEnd = () => this.props.setCurrentLineIndex(this.props.currentLineIndex + 1);

2020 年更新

Hooks 让它变得简单了很多,不需要类组件,只需使用一个效果:

const scrollToCurrentLine = useCallback(() => {
  const currentLineEl = document.getElementById(currentLineIndex);
  currentLineEl.scrollIntoView({ block: 'start', behaviour: 'smooth' });
}, [currentLineIndex]);

useEffect(scrollToCurrentLine, [scrollToCurrentLine]);

【讨论】:

    【解决方案2】:

    我通过创建一个小的 npm 模块解决了类似的问题。它允许您订阅和侦听 redux 操作,并在状态更改完成后立即执行提供的回调函数。用法如下。在您的 componentWillMount 或 componentDidMount 挂钩中:

     subscribeToWatcher(this,[
          {  
            action:"SOME_ACTION",
            callback:()=>{
              console.log("Callback Working");
            },
            onStateChange:true
          },
        ]);
    

    详细文档可以在this link找到

    【讨论】:

      【解决方案3】:

      一种解决方案是定义setCurrentLineIndex 以便它接收回调。

      //assuming the parent container is a class
      setCurrentLineIndex = (index, cb)=>{
          //write the logic here then execute the callback 
          cb()
      }
      
      // Then in your child component, you could do something like this 
          setCurrentLineIndex(nextIndex, scrollToCurrentLine)
      

      【讨论】:

        猜你喜欢
        • 2019-03-16
        • 1970-01-01
        • 2021-05-12
        • 2021-06-11
        • 2022-01-06
        • 2019-08-18
        • 2019-12-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多