Замена return на dispatch приводит к ошибке

#react-redux

#react-redux

Вопрос:

Глядя на простое приложение, я пытаюсь понять Redux. Вы можете найти приложение здесь: простое приложение Redux

В документации Redux говорится: «Единственный способ изменить состояние внутри хранилища — это отправить действие«

Но создатель действия в этом приложении выглядит следующим образом:

 export const selectSong = song => {
  return {
    type: "SONG_SELECTED", 
    payload: song 
  };
};
  

Очевидно, что действие не отправлено. Он возвращается. Итак, я подумал, что произойдет, если я изменю функцию так, чтобы она отправляла действие:

 export const selectSong = song => {
  dispatch({
    type: "SONG_SELECTED", 
    payload: song 
  });
};
  

Но это вызывает следующую ошибку:

Не удалось скомпилировать./src/actions/index.js Строка 4: ‘dispatch’ не определен no-undef

Может кто-нибудь, пожалуйста, объяснить, почему?

Ответ №1:

На самом деле действие здесь является отправкой.

Функции connect обычно передается 1 или 2 аргумента:

Первый аргумент: функция, которая извлекает фрагменты состояния из Redux и присваивает их реквизитам, которые будет использовать ваш компонент React.

Второй аргумент: функция, которая связывает функции создателя действия, чтобы вам не приходилось писать props.dispatch(ActionName()) повсюду, вы можете просто написать props.ActionName()

https://daveceddia.com/redux-mapdispatchtoprops-object-form/

Комментарии:

1. Спасибо. Но, честно говоря, я все еще не понимаю, почему я должен использовать return вместо dispatch в этом примере.

2. Вы не можете использовать dispatch, потому что вы не передаете dispatch prop этой функции. Создатели действий должны возвращать простые объекты. В вашем случае connect автоматически переносит функцию в вызов dispatch. blog.bam.tech/developper-новости/…

Ответ №2:

Ошибка заключается в том, что dispatch нигде не определено. Сам по себе Redux (без промежуточных программ) ожидает объекты, описывающие действия. Отправка в вашем примере кода связана с redux с помощью функции react-redux connect более высокого порядка, поэтому вам не нужно вызывать dispatch явно.

Форму диспетчерских действий с явным использованием dispatch я видел только при использовании промежуточного программного обеспечения, подобного redux-thunk .

redux-thunk:

Thunks — рекомендуемое промежуточное программное обеспечение для базовой логики побочных эффектов Redux, включая сложную синхронную логику, которой требуется доступ к хранилищу, и простую асинхронную логику, такую как AJAX-запросы.

Это означает, что вы можете возвращать функции.

И вместо:

 export const selectSong = song => {
  return {
    type: "SONG_SELECTED", 
    payload: song 
  };
};
  

Вы можете:

 export const selectSong = song => {
  return (dispatch, getState) => {
    const { songs } = getState() // You can access state with getState
    dispatch({
      type: "SONG_SELECTED",
      payload: song
    });
  };
};
  

Вот ссылка на ваш пример кода с redux-thunk:

https://codesandbox.io/s/1pr283o8l

И вот еще одна ссылка на ‘redux’ с аналогичным кодом thunk:

https://redux.js.org/advanced/async-actions#actionsjs-asynchronous

Ответ №3:

С удовольствием, итак, что здесь происходит, у вас есть action creator, который возвращает объект action, и в этом объекте action у вас есть свойство type и payload .

Чтобы иметь возможность превратить ваш action creator в тот, который может возвращать функцию вместо объекта action, вам нужно решить, собираетесь ли вы устанавливать промежуточное программное обеспечение, подобное redux-thunk , и использовать его в сочетании.

Именно из этой библиотеки мы получаем аргументы dispatch и getState , которые мы можем использовать для передачи функции вместо объекта action от наших создателей action.

После того, как вы импортировали и установили redux-thunk , я полагаю, вам пришлось бы реорганизовать свой action creator следующим образом:

Перед:

 // Action creator
export const selectSong = (song) => {
  // returns an action
  return {
    type: 'SONG_SELECTED',
    payload: song
  };
};
  

После:

 export const selectSong = (song) => async dispatch => {
  const response = await songsAPI.get("/songs");
  dispatch({ type: "SONG_SELECTED", payload: song });
};
  

Теперь я не знаю, извлекаете ли вы песню из внешнего API, но я написал код таким образом, чтобы подчеркнуть, что это то, что вы могли бы реализовать, когда хотите разработать создатели асинхронных действий, что также является смыслом использования промежуточного программного обеспечения, подобного redux-thunk , и рефакторинга вашего создателя действий таким образом, потому что Redux не выполняет асинхронные запросы «из коробки».

Обратите внимание, что я не использую getState здесь в качестве аргумента, потому что, если вам это не понадобится, тогда, пожалуйста, не определяйте это, но если вы используете VS Code, должна быть волнистая строка, кричащая вам, что вы не использовали аргумент, или getState должна быть заштрихована, указывающая, что вы его нигде не использовали, это подсказка, в ней говорится, что оставьте это, если вы не собираетесь его использовать.