Custom Hook получает обещание - PullRequest
0 голосов
/ 08 мая 2019

Я создал Custom Hook.В этом хуке я получаю обещание от loadRates():

export const actions = {
  updateRate: () =>
    loadRates()
      .then(response => ({
        type: types.UPDATE_RATE,
        value: response
      }))
      .catch(reject => ({
        type: types.ERROR_UPDATE_RATE,
        value: reject
      }))
};

export const reducer = (state, action) => {
  switch (action.type) {
    case types.UPDATE_RATE:
      return { ...state, rates: action.value, loading: false };
    case types.ERROR_UPDATE_RATE:
      return { ...state, error: action.value, loading: false };
    default:
      throw new Error("Action type must be defined");
  }
};

Проблема в том, что даже если у меня response от loadRates(), я получаю ошибку Action type must be defined, потому что мойstate - это pending.

Что я должен сделать, чтобы исправить эту проблему?

Заранее спасибо!

Редактировать: коды и поле здесь

1 Ответ

0 голосов
/ 09 мая 2019

Проблема в том, что функция dispatch из useReducer, полученная из Store.js, вызывается с Promise, возвращением actions.updateRate в ratesReducer.js.

Этот параметр dispatch должен быть объектом со свойством типа (то же самое в редуксе). Одним из способов решения вашей проблемы будет отправка, когда обещание разрешается или отклоняется. В Redux вы можете использовать Thunk, для этого есть библиотека. При этом я опишу, как работает Thunk, чтобы у вас был лучший обзор. Давайте улучшим базовую диспетчеризацию и передадим ее провайдеру контекста:

export const StoreProvider = props => {
  const [state, dispatch] = useReducer(reducer, initialState);

  const thunkDispatch = action => {
    if (typeof action === "function") {
      return action(dispatch);
    }

    return dispatch(action);
  };

  return (
    <StoreContext.Provider value={{ state, actions, dispatch: thunkDispatch }}>
      {props.children}
    </StoreContext.Provider>
  );
};

Ваши асинхронные действия теперь могут быть функциями, которые принимают диспетчеризацию в качестве параметра.

const updateRate = dispatch => // get dispatch from parameters
  loadRates()
    .then(response => dispatch({ // add dispatch here
      type: types.UPDATE_RATE,
      value: response
    }))
    .catch(reject => dispatch({ // add dispatch here too
      type: types.ERROR_UPDATE_RATE,
      value: reject
    }))

Вот обновленная ручка: https://codesandbox.io/s/3qx982292p. Посмотрите на redux-thunk, эта проблема не нова, и для нее уже есть много знаний.

...