React:Redux状态在一个效果中更新但在同一组件中的下一个效果是使用先前的state值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React:Redux状态在一个效果中更新但在同一组件中的下一个效果是使用先前的state值相关的知识,希望对你有一定的参考价值。

使用反应16.8.2,hooks API

Redux初始状态:

const initialState = {
  name: one,
  count: 1,
}

零件:

function CompTwo(props) {
  useActiveCount(setActiveCount, 2); 
  useEffect(() => {
    // activeCount is still 1
    if(activeCount === 2) {
      setActiveName('two')
    }
  });
}

const mapStateToProps = state => ({
  activeCount: state.count,
});

const mapDispatchToProps = dispatch => ({
  setActiveCount: count => dispatch(updateActiveCount(count)),
  setActiveName: name => dispatch(updateActiveName(name),
});

export default connect(mapStateToProps, mapDispatchToProps)(CompTwo);

useActiveCount:

const useActiveCount = function (setActiveCount, count) {
  useEffect(() => {
    setActiveCount(count);
  })
}

CompTwo,如果我在设置活动名称useActiveCount(setActiveCount, 2);之前设置计数setActivePage('two'),我不应该在2道具中获得新值activeCount吗?

它确实将activeCount设置为2,当我在dev-tool控制台中检查redux logger中的状态值时,但是在useEffectCompTwo代码中,我仍然得到activeCount的旧值,即1

为什么会这样?

答案

你需要将activeCount传递给useEffect钩子,否则一旦动作完全完成就不会重新触发钩子。

function CompTwo({ activeCount, setActiveCount, setActiveName }) {
  useActiveCount(setActiveCount, 2); 
  useEffect(() => {
    if(activeCount === 2) {
      setActiveName('two');
    }
  }, [activeCount]);
}

可运行的例子:

// Custom hook

const useActiveCount = (setActiveCount, count) => {
  React.useEffect(
    () => {
      setActiveCount(count);
    }, [count]
  );
};

// Redux types

const SET_ACTIVE_COUNT = "SET_ACTIVE_COUNT";

const SET_ACTIVE_NAME = "SET_ACTIVE_NAME";

// Redux actions

const updateActiveCount = count => ({
  type: SET_ACTIVE_COUNT,
  count,
});

const updateActiveName = name => ({
  type: SET_ACTIVE_NAME,
  name,
});

// Redux Reducer

const reducer = (state = { count: 0 }, action) => {
  switch (action.type) {
    case SET_ACTIVE_COUNT:
      return {
        ...state,
        count: action.count
      };
    case SET_ACTIVE_NAME:
      return {
        ...state,
        name: action.name
      };
    default:
      return state;
  }
};

const store = Redux.createStore(reducer);

// Comp 2

function CompTwo({ activeCount, activeName, setActiveCount, setActiveName }) {
  useActiveCount(setActiveCount, 2);
  React.useEffect(() => {
    console.log(activeCount);
    if (activeCount === 2) {
        console.log('hit');
        setActiveName('Two');
    }
  }, [activeCount]);
  return (
    <React.Fragment>
        <h5>Count: {activeCount}</h5>
        <h5>Name: {activeName}</h5>
    </React.Fragment>
  );
}

const mapStateToProps = state => ({
  activeCount: state.count,
  activeName: state.name,
});

const mapDispatchToProps = dispatch => ({
  setActiveCount: count => dispatch(updateActiveCount(count)),
  setActiveName: name => dispatch(updateActiveName(name)),
});

const Comp = ReactRedux.connect(
  mapStateToProps,
  mapDispatchToProps
)(CompTwo);

// App

const App = () => (
  <ReactRedux.Provider store={store}>
    <Comp />
  </ReactRedux.Provider>
);

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/6.0.1/react-redux.min.js"></script>
<div id="root"></div>

以上是关于React:Redux状态在一个效果中更新但在同一组件中的下一个效果是使用先前的state值的主要内容,如果未能解决你的问题,请参考以下文章

React / Redux:mapStateToProps 实际上并未将状态映射到道具

Redux - 状态正在更新,但 React 组件没有

在通过动作调度进行状态更新后,在 React 中使用 Redux 执行函数?

在 react-redux 应用程序中更新部分状态时,整个页面闪烁并跳转到顶部

React Native 和 Redux:为啥子组件不会在每次状态更新时重新渲染?

REACT + REDUX:在 redux 状态更改时 mapStateToProps 更新状态,但视图未按照新状态呈现