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

问题描述 投票:1回答:1

使用反应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

为什么会这样?

reactjs redux react-redux react-hooks
1个回答
2
投票

你需要将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>
© www.soinside.com 2019 - 2024. All rights reserved.