Реакция: Состояние Redux обновлено в одном эффекте, но следующий эффект в том же компоненте использует предыдущее значение состояния - PullRequest
1 голос
/ 23 марта 2019

Использование реакция 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);

useActiveCount

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

В CompTwo, если я установлю счет useActiveCount(setActiveCount, 2); перед установкой активного имени setActivePage('two'), я не должен получить новое значение 2, в activeCount prop?

Устанавливается activeCount в 2, когда я проверяю значение состояния в логере резервирования в консоли dev-tool, но в useEffect коде CompTwo я все равно получаю более старое значение activeCount, то есть 1.

Почему это происходит?

1 Ответ

2 голосов
/ 23 марта 2019

Вам нужно передать 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...