#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;
}
}
}