Как использовать общий API для отправки нескольких создателей действий в redux?

#reactjs #redux

#reactjs #redux

Вопрос:

У меня есть 2 объекта в моем состоянии, и я вызываю общий API для получения данных, передавая id запрос.

Ниже приведен мой fetch вызов для первого раздела, который запускает receiveSectionA для обновления sectionA в моем состоянии.

 export function fetchSection(sectionCode){
  return(dispatch,getState,api)=>{
    const endPoint = 'url/?sectionCode=' sectionCode
    const  method = 'GET'
    const isAuth = true
    const promise = api(endPoint,method,isAuth)
    promise
    .then(response =>
      response.json().then(json => ({
        status:response.status ,
        json
      })
    ))
    .then(
      ({ status, json }) => {
        if( status >= 200 amp;amp; status < 300) {
          const sectionDictionary = utils.convertSectionsToDictionary(camelizeKeys(json))
          dispatch(receiveSectionA(sectionDictionary))
        }
        if (status >= 400 ) {
          //throw error
        }
      },
      err => {
        console.log("error" err);
      }
    );
  }
}
  

Теперь я делаю тот же вызов для sectionB, который запускает следующее :-

 dispatch(receiveSectionB(sectionDictionary))
  

Теперь, поскольку приведенный выше fetch вызов такой же, могу ли я каким-либо образом сделать это универсальным. Я чувствую, что слишком много повторений кода.

Я думал о случаях переключения для отправки различных действий на основе sectionCode, но у меня около 20 разделов, и я думаю, что код станет действительно сложным.

Есть ли лучший способ справиться с этим?

Ответ №1:

Как я понимаю, вы ищете dynamic function call . Вы можете использовать eval , что может привести к неожиданному результату. Поэтому используйте с осторожностью.

Ожидая, что у вас есть две функции как receiveSectionA и receiveSectionB ;

 export function fetchSection(sectionCode){
  return(dispatch,getState,api)=>{
     ....................
    ))
    .then(
      ({ status, json }) => {
        if( status >= 200 amp;amp; status < 300) {

          const sectionDictionary = utils.convertSectionsToDictionary(camelizeKeys(json))
          let funToCall = 'receiveSection'   sectionCode   '(sectionDictionary )'; // preparing function to call
          dispatch(eval(funToCall)); // Calling Function
        }
        if (status >= 400 ) {
          //throw error
        }
      },
      err => {
        console.log("error" err);
      }
    );
  }
}
  

Редактировать:
Подробнее об eval этом Security разделе —
https://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood /

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

1. это выглядит интересно. Но что вы подразумеваете под неожиданными результатами?

2. ответ обновлен ссылками.. Читайте, изучайте, забывайте … : D

Ответ №2:

Немного поразмыслив над этим, очевидно eval , что это не очень хороший вариант.

Я подумал, что попробую одну из удивительных вещей, которые поддерживает Javascript, которая передает функции в качестве параметров.

При отправке действия я передаю receiveActionCreator в качестве обратного вызова.

так что мой fetch теперь будет:-

 export function fetchSection(callback,sectionCode){
  return(dispatch,getState,api)=>{
     ....................
    ))
    .then(
      ({ status, json }) => {
        if( status >= 200 amp;amp; status < 300) {

          const sectionDictionary = utils.convertSectionsToDictionary(camelizeKeys(json))

          dispatch(callback(sectionDictionary)); // Calling Function
        }
        if (status >= 400 ) {
          //throw error
        }
      },
      err => {
        console.log("error" err);
      }
    );
  }
}
  

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

Ответ №3:

Я не вижу большую часть вашего кода из reducer, но мне кажется, что у вас слишком много логики вокруг действий. Обычно действие предназначено только для изменения состояния приложения, поэтому дважды подумайте о форме состояния вашего приложения и просто предоставьте минимальную информацию в действиях, чтобы ваш редуктор мог вычислить состояние. Кроме того, если вам нужно преобразовать json и проверить код состояния для каждого запроса, почему бы не сделать это в модуле api, если вы ничего не можете сделать с ошибками, тогда вам не следует их обрабатывать, обрабатывать в api или отражать их в состоянии приложения. Бизнес-логика приложения всегда находится в редукторах. После этого ваше действие будет выглядеть лучше, и вы не будете беспокоиться о повторении кода. Надеюсь, это вам поможет.

Ответ №4:

Итак, после поиска этого я, наконец, нашел то, что я прочитал в redux-docs .

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

Следующий код должен действительно четко объяснить это. Это из самой документации.

 function createCounterWithNamedType(counterName = '') {
    return function counter(state = 0, action) {
        switch (action.type) {
            case `INCREMENT_${counterName}`:
                return state   1;
            case `DECREMENT_${counterName}`:
                return state - 1;
            default:
                return state;
        }
    }
}