首页 > 解决方案 > React:Redux 状态在一个效果中更新,但同一组件中的下一个效果正在使用先前的状态值

问题描述

使用react 16.8.2钩子 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);

使用活动计数

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

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

当我在开发工具控制台中检查 redux 记录器中的状态值时,它确实设置activeCount为 2,但是在 的useEffect代码中CompTwo,我仍然得到activeCountie的旧值1

为什么会这样?

标签: reactjsreduxreact-reduxreact-hooks

解决方案


您需要将 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>


推荐阅读