#javascript #reactjs
#javascript #reactjs
Вопрос:
Это может быть дубликат, поскольку я считаю, что это обычная ситуация, но я не могу найти в Stack Overflow ничего, что отвечало бы на мой вопрос.
Я установил объект, который содержит мое начальное состояние следующим образом (извлеките, чтобы показать только соответствующие значения для этого вопроса):
export const initialState = {
signUpDialog: {
open: false,
nameField: {
isEmpty: false,
isInvalid: false
}
}
Как вы можете видеть, open
состояние вложено на 1 глубину в signUpDialog, однако isEmpty
и isInvalid
вложено на 2 глубины.
Я использую перехватчики реакции для управления состоянием, и у меня есть создатель следующего действия для передачи значений в мой редуктор состояния:
export const TOGGLE_BOOLEAN = "TOGGLE_BOOLEAN";
export function toggleBoolean(state, subState, value) {
return {
type: TOGGLE_BOOLEAN,
payload: {
state: state,
subState: subState,
value: value
}
};
}
И следующий редуктор, который изменяет состояние (примечание: state
параметр равен текущему состоянию, а action
параметр равен возвращаемому значению создателя toggleBoolean
действия):
const reducer = (state, action) => {
const reduced = { ...state };
switch (action.type) {
case TOGGLE_BOOLEAN:
return Object.assign({}, state, {
...reduced,
[action.payload.state]: {
...reduced[action.payload.state],
[action.payload.subState]: action.payload.value
}
});
default:
state;
}
};
Это отлично работает для обновления open
состояния, поскольку оно вложено только на 1 глубину при действии.payload.state=’signUpForm’, однако это не будет работать для name: { isEmpty}
или name: { isInvalid }
, поскольку они оба вложены на 2 глубины.
Я знаю, что мог бы решить эту проблему, используя разных создателей действий и переключая случаи для каждого уровня глубины, однако это не было бы СУХИМ, поскольку они, по сути, делают одно и то же.
Есть ли какие-либо более простые СУХИЕ решения для этого?
Ответ №1:
Вот простой набросок кода. Возможно, это поможет вам найти решение —
const setKV = (k, v) => (o = {}) =>
({ ...o, [k]: v })
const setDeepKV = (k, v, ...more) => (o = {}) =>
more.length === 0
? setKV (k, v) (o)
: setKV (k, setDeepKV (v, ...more) (o [k])) (o)
const print = (...vs) =>
vs .forEach (v => console.log (v))
print
( setDeepKV ('a', 'X') ({})
// { a: 'X' }
, setDeepKV ('a', 'X') ({ a: 1, b: 2 })
// { a: 'X', b: 2 }
, setDeepKV ('a', 'a1', 'a2', 'X') ({ a: 1, b: 2 })
// { a: { a1: { a2: 'X' } }, b: 2 }
, setDeepKV ('a', 'b', 'c', 'X') ({ a: { b: { c: 1, d: 2 } }, e: 3 })
// { a: { b: { c: 'X', d: 2 } }, e: 3 }
, setDeepKV ('a', 'b', 'X') ({ a: { b: { c: 1, d: 2 } }, e: 3 })
// { a: { b: 'X' }, e: 3 }
)
Комментарии:
1. Спасибо, мне удалось заставить его работать, используйте это в качестве примера. Я отредактирую свой пост, чтобы включить в него свое решение.