Доступ к состоянию редуктора из другого редуктора
У меня есть редуктор, посредством которого я перенастраиваю соответствующее состояние при отправке действия. Теперь я вызываю API через равные промежутки времени, поэтому результат будет вызывать действие снова и снова. Итак, я хочу, чтобы, если состояние редуктора уже имело данные, то другой редуктор не отображал состояние загрузки во время отправки вызова. Он должен поддерживать свое состояние загрузки только при первом получении данных. Я надеюсь, что смогу объяснить это правильно
Вот мои фрагменты кода
Редуктор состояния нагрузки
const loading = (state = false, action) => {
switch (action.type) {
case 'GET_AUDIT_DATA': // here I want to return true only when there is no data available
return true
case 'GET_AUDIT_DATA_RECEIVED':
return false
case 'GET_AUDIT_DATA_ERROR':
return false
default:
return state
}
}
Объединение редукторов
const allReducers = combineReducers({
auditData: AuditData,
auditLoading: AuditLoading,
modifiedOrders: ModifiedOrders
});
export default allReducers;
Редуктор возвращает данные о действии, вызванном суперагентом
const auditData = (state = [], action) => {
switch(action.type) {
case 'GET_AUDIT_DATA_RECEIVED':
console.log(action.data);
return action.data;
case 'GET_AUDIT_DATA_ERROR':
return action.err;
default :
return state;
}
}
export default auditData;
Так что изначально auditData
не содержит никаких данных, только после первого успешного вызова возвращает данные. Когда это вызывается одновременно loading state reducer
называется, и он должен вернуть истину в GET_AUDIT_DATA
действие только в том случае, если редуктор данных аудита не содержит никаких данных.
Также возвращает только текущие полученные данные из auditData
правильный путь или я должен сделать это по-другому. В основном я хочу overwrite
current data
с new one
,
5 ответов
Лучший способ продолжить - отправить в редуктор состояния загрузки информацию, чтобы узнать, есть ли у другого редуктора данные. Иметь в конце:
const loading = (state = false, action) => {
switch (action.type) {
case 'GET_AUDIT_DATA':
if(!action.dataAlreadyInitialized){
return true
}
case 'GET_AUDIT_DATA_RECEIVED':
return false
case 'GET_AUDIT_DATA_ERROR':
return false
default:
return state
}
}
Вы должны иметь доступ от вашей функции действия к состоянию приложения и делать:
dispatch({
type:'GET_AUDIT_DATA',
dataAlreadyInitialized: appState.auditData.length > 0
});
Ты можешь позвонить getState()
через магазин, чтобы получить список редукторов и текущее состояние внутри редукторов.
- Импортировать
store
вauditLoading
(используйте хранилище, чтобы получить значения. Не изменяйте хранилище) store.getState().auditLoading
даст вам состояниеauditLoading
редуктор.
Этот подход похож на обратный вызов, предоставляемый redux-thunk
, В котором (dispatch, getState) => {}
будут возвращены к действию.
Надеюсь это поможет!
Принятый ответ хорош (передать длину данных через действие), но может оказаться трудоемким, если это часть информации, которая широко используется. Есть другое решение, которое иногда предпочтительнее для чего-то вроде "текущего пользователя", которое может использоваться при каждом действии.
Согласно Redux FAQ https://redux.js.org/faq/reducers, вполне допустимо добавить третий аргумент в функцию reducer. Т.е.:
Редуктор состояния нагрузки
const loading = (state = false, action, noData) => {
switch (action.type) {
case 'GET_AUDIT_DATA':
return noData
case 'GET_AUDIT_DATA_RECEIVED':
return false
case 'GET_AUDIT_DATA_ERROR':
return false
default:
return state
}
}
Комбинирование редукторов
К сожалению, это означает, что мы должны писать код для объединения редукторов, а не использовать ярлык combReducers. Но это не так уж сложно, вы просто вызываете каждый редуктор и создаете новый объект, если что-то изменилось:
const allReducers = (state = null, action) => {
const auditData = AuditData(state?.auditData, action);
const auditLoading = AuditLoading(state?.auditLoading, action, !state?.auditData?.length);
const modifiedOrders = ModifiedOrders(state?.modifiedOrders, action);
return (auditData !== state?.auditData ||
auditLoading !== state?.auditLoading ||
modifiedOrders !== state?.modifiedOrders) ?
{ auditData, auditLoading, modifiedOrders } : state;
});
export default allReducers;
Обратите внимание на третий аргумент, переданный редуктору AuditLoading. Никаких изменений в других редукторах или в коде, вызывающем действие, не требуется. Что приятно!
import store from '../../../redux/store'
console.log(store.getState().loginReducer.accessToken)
Благодаря этому заявлению мы получим состояние accessToken
Вы можете использовать Thunk, чтобы решить эту проблему.
Предположим, что ваш создатель действий выглядит так
const getAuditDataAction = (data) => {
return { type: "GET_AUDIT_DATA", data }
}
Вам нужно будет добавить промежуточное программное обеспечение Redux Thunk, если у вас его еще нет.
Создатель вашего действия может стать чем-то вроде этого
const getAuditDataAction = (data) => {
return async (dispatch, getState) => {
const { auditData, auditLoading, modifiedOrders } = getState();
// Here depending on data you have in your store you
// can dispatch the default action or another action
// that does something else
dispatch({ type: "GET_AUDIT_DATA", data })
}
}