#reactjs #redux #react-redux
#reactjs #redux #реагировать-redux
Вопрос:
Я провел некоторое исследование возможных способов сделать это, но я не могу найти тот, который использует ту же архитектуру, что и в приложении, над которым я работаю. Например, в документах React говорится, что у нас должен быть метод, который выполняет HTTP-запрос, а затем вызывает действия в разных точках (при запуске запроса, при получении ответа и т. Д.). Но у нас есть другой подход. Мы используем действие, которое выполняет HTTP-вызов, а затем отправляет результат. Если быть более точным, мой вариант использования таков:
// action to get resource A
getResourceA () {
return dispatch => {
const result = await axios.get('someLink');
dispatch({
type: GET_RES_A,
payload: result
});
};
}
// another action which needs data from resource A
getSomethingElseByIdFromA (aId) {
return async dispatch => {
const result = await axiosClient.get(`someLink/${aId}`);
dispatch({
type: GET_SOMETHING_BY_ID_FROM_A,
payload: result
});
};
}
Как указано, для второго действия требуются данные из первого.
Теперь я знаю два способа сделать это:
- возвращает результат первого действия
getResourceA () {
return async dispatch => {
const result = await axios.get('someLink');
dispatch({
type: GET_RES_A,
payload: result
});
return resu<
};
}
// and then, when using it, inside a container
async foo () {
const {
// these two props are mapped to the getResourceA and
// getSomethingElseByIdFromA actions
dispatchGetResourceA,
dispatchGetSomethingElseByIdFromA
} = this.props;
const aRes = await dispatchGetResourceA();
// now aRes contains the resource from the server, but it has not
// passed through the redux store yet. It's raw data
dispatchGetSomethingElseByIdFromA(aRes.id);
}
Однако проект, над которым я работаю прямо сейчас, хочет, чтобы данные сначала проходили через хранилище — на случай, если его необходимо изменить, — и только после этого его можно использовать. Это привело меня ко 2-му способу действий:
- создайте «агрегированный» сервис и используйте
getState
метод для доступа к состоянию после завершения действия.
aggregateAction () {
return await (dispatch, getState) => {
await dispatch(getResourceA());
const { aRes } = getState();
dispatch(getSomethingElseByIdFromA(aRes.id));
};
}
И после этого просто вызовите это действие в контейнере.
Мне интересно, подходит ли второй способ. Я чувствую, что нехорошо иметь вещи в хранилище redux только ради доступа к ним во время действий. Если это так, каков был бы лучший подход к этой проблеме?
Ответ №1:
Я думаю, что наличие / использование Epic
from redux-observable
было бы наилучшим образом подходящим для вашего варианта использования. Это позволило бы сначала выполнять действия во всех ваших редукторах (в отличие от упомянутого выше подхода), прежде чем обрабатывать их в ТОЙ ЖЕ логике. Кроме того, использование потока действий позволит вам манипулировать данными во всем их потоке, и вам не придется хранить ненужные вещи. Реактивное программирование и сам наблюдаемый шаблон имеют некоторые большие преимущества, когда дело доходит до асинхронных операций, лучший вариант, чем redux-thunk, sagas и т. Д. imo.
Комментарии:
1. Я взглянул на библиотеку redux-observable. Это действительно возможно и может решить проблему. Однако мне бы понравился подход, который не требовал бы использования другой библиотеки. Я также узнал о новых пакетных действиях, представленных Redux в их последнем обновлении. Возможно, они могли бы помочь.
Ответ №2:
Я бы взглянул на использование пользовательского промежуточного программного обеспечения (https://redux.js.org/advanced/middleware ). Использование промежуточного программного обеспечения может упростить достижение такого рода целей.
Что-то вроде :
import {GET_RESOURCE_A, GET_RESOURCE_B, GET_RESOURCE_A_SUCCESS, GET_RESOURCE_A_ERROR } from '../actions/actionTypes'
const actionTypes = [GET_RESOURCE_A, GET_RESOURCE_B, GET_RESOURCE_A_SUCCESS, GET_RESOURCE_A_ERROR ]
export default ({dispatch, getState}) => {
return next => action => {
if (!action.type || !actionTypes.includes(action.type)) {
return next(action)
}
if(action.type === GET_RESOURCE_A){
try{
// here you can getState() to look at current state object
// dispatch multiple actions like GET_RESOURCE_B and/ or
// GET_RESOURCE_A_SUCCESS
// make other api calls etc....
// you don't have to keep stuff in global state you don't
//want to you could have a varaiable here to do it
}
catch (e){
} dispatch({type:GET_RESOURCE_A_ERROR , payload: 'error'})
}
}
}
Комментарии:
1. Извините, я не понимаю ваш пример, и я не думаю, что промежуточное программное обеспечение — это то, что я ищу. Промежуточное программное обеспечение будет вызываться каждый раз, когда я отправляю действие. Я просто хочу, чтобы действие использовало данные, полученные в другом действии. Промежуточное программное обеспечение, похоже, перестраивает вещи.
2. Но, конечно, вы можете перехватить действие в промежуточном программном обеспечении, использовать его по своему усмотрению и получить текущее состояние, если оно вам нужно в этом сравнении, и отправить второе действие, но оно обойдет промежуточное программное обеспечение, если его нет в вашем массиве ActionTypes ? Или я неправильно понимаю (очень возможно)