Я работаю над проектом, в котором я хочу, чтобы данные хранились отдельно (хотя и в одном хранилище redux). Предполагая, что я хочу различать данные, считается ли следующая идея антипаттерном?
Действие:
export const GET_DATA = 'GET_DATA';
export const getData = () => {
return async (dispatch) => {
try {
const data = await axios.get('/data');
return onSuccess(data.data.response);
} catch (err) {
return onError(err);
}
function onSuccess(data) {
dispatch({ type: 'GET_DATA', data });
}
function onError(error) {
dispatch({ type: 'ERROR', error });
}
}
}
Редуктор:
import * as actionTypes from '../actionTypes';
const initialState = {
data: [],
};
export default (state = initialState, action) => {
switch (action.type) {
case actionTypes.GET_DATA:
return {
...state,
data: action.data
}
default:
return state;
}
};
Теперь я хочу разделить data на data0 и data1 (см. Action). Я подумал о добавлении другого свойства ко второму аргументу, который передается редуктору, например. превращение:
function onSuccess(clients) {
dispatch({ type: 'GET_DATA', data });
}
в
function onSuccess(clients) {
dispatch({ type: 'GET_DATA', data, classification: data0 });
}
Это позволило бы мне переписать свой Редуктор на:
import * as actionTypes from '../actionTypes';
const initialState = {
data0: [],
data1: []
};
export default (state = initialState, action) => {
switch (action.type) {
case actionTypes.GET_DATA:
switch (action.classification) {
case 'data0':
return {
...state,
data: action.data
}
case 'data1':
return {
// ...
}
}
default:
return state;
}
};
Однако я не уверен, считается ли это антипаттерном? Не могли бы вы поделиться своими мыслями по этому поводу или порекомендовать другое (лучшее) решение? В качестве альтернативы я сейчас вижу много действий ... например. GET_DATA_DATA0, GET_DATA_DATA1 ...
Спасибо!





Я считаю, что это очень труднодостижимый и неясный способ что-либо делать в будущем.
Для каждого типа имеющихся данных вы хотите создать новый редуктор. В моем личном проекте есть редуктор user, conversations и chat.
Иногда наличие небольших функций кажется глупым и бессмысленным, пока вы не начнете масштабировать и не поймете, что это изменило, и как мне точно следить за тем, что произошло.
У меня есть файл initialState.js, который я использую для заполнения начального состояния редуктора, что помогает новым разработчикам лучше понять, где находятся данные.
export default {
chat: {
id: null,
messages: [],
},
conversations: [],
user: {
id: null,
name: '',
}
}
Каждый редуктор теперь очень ясно дает понять при отправке действия, что произошло и какие данные обновляются.
Так что для chatReducer это будет выглядеть так:
import * as actionTypes from '../actionTypes';
import initialState from '../store/initialState.js'
export default (state = initialState.chat, action) => {
switch (action.type) {
case actionTypes.RECEIVED_NEW_MESSAGE:
return { ...state, messages: [...state.message, action.newMessage]}
case actionTypes.FETCHED_CHAT_SUCCESS:
return action.chat
default:
return state;
}
};
Последнее, что я хотел бы оставить вам, это подумать о тестировании и о том, что легче тестировать, и как тесты придадут вам уверенности в рефакторинге в будущем.
Спасибо за ваш вклад. Вы написали: «Для каждого типа имеющихся данных вы хотите создать новый редуктор, поэтому для моего приложения у меня есть пользователь, диалоги и редуктор чата». Верно, но в этом случае (я должен сказать, что не должен называть это данными в своих примерах) тип данных тот же, например инструмент, который может контролировать различные системы. В каждой системе одни и те же данные (хранилища, сервисы и т. д.), Однако мне все равно приходится различать их.
Извините, грамматика - не моя сильная сторона>. <Но есть ли в этом смысл? @Faizy
@ twils0 правильно. Наличие одного файла initialState для нескольких редукторов похоже на проблему. Как правило, разделение на мельчайшие части, хотя и утомительно с самого начала, действительно окупается, когда приложение масштабируется и вы пытаетесь отладить.
@ 223seneca и twils0 Спасибо за отзыв, я буду помнить об этом, поскольку мои приложения продолжают расти. Можете ли вы подробнее объяснить, почему вам кажется, что это вызывает проблемы? Просто любопытно, потому что у меня он еще не укусил меня, и я предпочитаю останавливать плохие шаблоны, если есть лучший шаблон.
Во-первых, если есть какая-то проблема с тем, как структурировано состояние, вы получите сразу несколько сбоев, если вы будете использовать одно и то же состояние для всех из них. С другой стороны, если у вас есть отдельный initialState, у вас есть единственная точка отказа, что упрощает определение проблемы.
@ 223seneca Есть другие причины? Думаю, я обнаружил, что остановка моего приложения с ошибкой, что состояние неправильно структурировано, подходит для меня, потому что я знаю, что я только что изменил свой initialState, и я знаю, где искать проблему / ide помогает остановить / найти эти проблемы.
Я имею ввиду, это только мое мнение. Делайте то, что считаете лучшим. Как бы то ни было, насколько я помню, все демонстрации, которые я изучил подробно, разработчики, гораздо более опытные в Redux, чем я использую отдельные initialState. Кроме того, в настоящее время я разрабатываю приложение, в котором разные initialState довольно большие и не связаны с другими частями приложения, так что это, вероятно, влияет и на мои инстинкты.
TallPaul, @ 223seneca Все дело в модульности. Существует множество статей о том, как структурировать файлы redux для хорошего масштабирования. В определенном смысле это больше искусство, чем наука. Когда вы говорите о сотнях редукторов, вы не хотите искать файл редуктора, что-то добавлять к нему, а затем искать файл initialState, который, вероятно, состоит из тысяч строк кода, прокрутите его некоторое время, чтобы найдите часть, относящуюся к только что измененному редуктору, а затем, наконец, измените эту часть состояния initialState. В редуктор проще поставить соответствующую деталь.
@ twils0 Это отличное объяснение, разъясняющее методы, которые я применил, даже не обдумывая причины, по которым я это сделал.
@ 223seneca, спасибо. Вы сказали примерно то же самое выше. Я не могу доверять слишком много. Я просто прочитал много статей, когда только начал, и понял, что нужно было организовать много файлов, ха-ха.
223seneca и @ twils0 спасибо за объяснение, большинство моих проектов не попали в сотни редукторов, поэтому, вероятно, еще не столкнулись с этой проблемой масштабирования
В зависимости от того, насколько велико значение initialState, вы можете разделить его - по одному initialState для каждого редуктора. Вместо импорта initialState и использования initialState.chat у вас будет просто объект initialState внутри редуктора чата, другой - внутри редуктора разговора и т. д.