React Hooks, Reducers, Ajax, как отправить новое состояние - PullRequest
0 голосов
/ 20 октября 2019

Пока не понимаю, как играть с асинхронным запросом и редуктором. Я не понимаюЯ использую крючки.

У меня есть что-то вроде этого:

const [state, dispatch] = useReducer((state, action) => {
    switch (action.type) {
        case 'GO':
            myFunctionThatDoesSomethingAsync(params);
            return {
                ...state,
                isChecking: true
            };
}

Тогда myFunctionThatDoesSomethingAsync довольно стандартно, я полагаю?

const myFunctionThatDoesSomethingAsync = (params) => {
fetch('/endpoint', {
    method: 'POST',
    headers: headers,
    body: body
})
    .then(response => response.json())
    .then(
        (result) => {
            if (result.status === 'failed') {
                // this does not work, dispatch is undefined of course
                dispatch({ type: 'FAILED', result: result });
            } else {
                // this does not work, dispatch is undefined of course
                dispatch({ type: 'DONE' });
            }
        }
    );
};

Я уверен, что мне не хватает концепции здесь. Я только начинаю работать с React, Reducers, Hooks и т. Д.

Я не знаю, нужно ли мне каким-либо образом передавать метод dispatch, но даже когда я вызываю myFunctionThatDoesSomethingAsync , dispatch метод еще не существует.

Я прочитал материал, связанный с async ключевыми словами, async actions и т. Д., Но не уверен, что он применим, и это было неясно.

Как я могу изменить свое состояние в этой ситуации? (У меня тот же код без Reducer, и он работает нормально, но потому что я могу использовать setSomething

1 Ответ

1 голос
/ 20 октября 2019

Редукторы должны быть чисто синхронизирующими функциями. Если вам нужно выполнить асинхронную операцию (вызвать api, setTimeout и т. Д.), Вызвать асинхронную функцию в теле компонента, и когда она будет выполнена, она должна отправить действие.

Например, я создал функцию asyncInc, которая отправляется через секунду. Редуктор обрабатывает действие при обычной отправке и увеличивает состояние.

const reducer = (count, step = 1) => count + step;

const App = () => {
  const [count, dispatch] = React.useReducer(reducer, 0);

  const asyncInc = React.useCallback(() => {
    setTimeout(() => dispatch(2), 1000); 
  }, [dispatch]);

  return (
    <div onClick={asyncInc}>{count}</div>
  );
};

ReactDOM.render(
  <App />,
  root
);
div {
  font-size: 2em;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>
...