Для меня полностью закрытие Xcode, а затем перезапуск проекта работал.
Это не решение исходного вопроса, я не верю, но это еще одна простая задача попробовать удаление файлов и папок и т. д. Подтвердите этот ответ для этой идеи.
UPD : теперь это часть ES2018.
Его можно немного улучшить с помощью нестандартизированного и все же синтаксиса распространения свойств . :
return {
...state,
notificationBar: {
...state.notificationBar,
open: true,
},
};
Все советы здесь велики и актуальны, но я бы хотел предложить другое решение. Проблема, которая здесь возникает, определенно является общей схемой, поэтому я думаю, что гораздо лучше просто написать собственный интерфейс для таких обновлений и придерживаться его внутри редукторов, а также использовать одну функцию для глубокого обновления внутри всех ваших редукторов.
Например, я создал библиотеку , где я попытался решить эту проблему следующим образом: я получаю тип модуля (так называемый «тайл»), функцию для выполнения операций ( как асинхронный, так и синхронизированный) и желаемое вложение на основе переданных параметров. Итак, для вашего случая это будет что-то вроде:
import { createSyncTile } from 'redux-tiles';
const uiTile = createSyncTile({
type: ['ui', 'elements'],
fn: ({ params }) => params,
// type will be `notificationBar`
nesting: ({ type }) => [type],
});
И это все - оно будет корректно обновляться при произвольной вложенности. Кроме того, плитка предоставляет селекторы, поэтому вам не нужно беспокоиться о том, где именно находятся данные, вы можете просто использовать их. Поэтому я не хочу сказать, что это лучшее решение, но идея довольно проста - не бойтесь написать собственную реализацию, а затем просто используйте фабрику для решения этой проблемы.
В дополнение к тому, что было сказано ранее, здесь есть функциональный способ с Рамда :
import { assocPath } from 'ramda';
const o1 = { a: { b: { c: 1 }, bb: { cc: 22 } } };
const o2 = assocPath(['a', 'b', 'c'])(42)(o1);
console.log(o1 !== o2, o1.a !== o2.a); // new copies of "changed" objects
console.log(o1.a.bb === o2.a.bb); // deep unchanged properties are copied by reference
Если вы используете Immutable.js , вы можете посмотреть в разделе Вложенные структуры некоторые функции, которые могут вам помочь, я лично использую mergeDeep
:
prevState.mergeDeep({ userInfo: {
username: action.payload.username,
} }),
Вы можете использовать линзы.
import { set, makeLenses } from '@DrBoolean/lenses'
const L = makeLenses(['notificationBar', 'open']);
const notificationBarOpen = compose(L.notificationBar, L.open)
const setNotificationBarOpenTrue = set(notificationBarOpen, true)
const a = { notificationBar: { open: false } }
const b = setNotificationBarOpenTrue(a)
// `a` is left unchanged and `b` is `{ notificationBar: { open: true } }`
Вы можете думать о линзах как о доступе / обновлении композиционных свойств.
Некоторые полезные ресурсы о линзах:
Если у вас все в порядке с чтением lisps , я бы также рекомендовал взглянуть на это превосходное введение в линзы из рэкетной документации . Наконец, если вы хотите пойти глубже и можете читать haskell , вы можете посмотреть: Линзы - композитный доступ к данным и манипулирование ими .
Хотя можно использовать оператор распространения, существует множество других способов достижения того же результата, даже не требуя будущего компилятора JS для нестандартизированной функции. Вот некоторые другие варианты в произвольном порядке.
Если вы уверены, что ваше состояние не будет расти, тогда вы можете просто вернуть все новое состояние в виде литерала.
return {
notificationBar: {
open: true
}
}
Однако, это не часто будет уместно, потому что маловероятно, что ваше состояние будет таким простым.
Redux предоставляет вам полезный метод для объединения нескольких редукторов, которые работают с различными частями объекта состояния. В этом случае вы бы создали редуктор notificationBar
, который обрабатывал бы только этот объект.
createStore(combineReducers({
notificationBar: function(state=initialNBarState, action) {
switch (action.type) {
case actions.LAYOUT_NOTIFICATIONBAR_OPEN:
return Object.assign({}, state, { open: true });
}
});
Это избавляет вас от необходимости беспокоиться о верхнем уровне свойств, так что вы можете избежать вложенных вызовов в Object.assign
.
Если ваше состояние может быть логически разбито на четко определенные разделы, то это, вероятно, самый идиоматический способ решения этой проблемы.
Вы можете использовать библиотеку постоянных структур данных для создания структур данных, которые можно изменить для возврата копии.
Мори - это результат компиляции структур данных и функционального API Clojure в JS.
import { hashMap, updateIn } from 'mori';
const initialState = hashMap(
"notificationBar", hashMap(
"open", false
)
);
// ...
return updateIn(state, ['notificationBar', 'open'], true);
ImmutableJS - это более императивный подход к переносу семантики попыток с отображением хэш-массивов из постоянных структур данных Clojure в Javascript.
import { Map } from 'immutable';
const initialState = Map({
notificationBar: Map({
open: true
});
});
// ...
return state.setIn(['notificationBar', 'open'], true);
Object.assign
Вы можете создать более дружественную версию Object.assign
для написания более кратких версий кода выше. Фактически, оно может быть почти таким же кратким, как оператор ...
.
function $set(...objects) {
return Object.assign({}, ...objects);
}
return $set(state, {
notificationBar: $set(state.notificationBar, {
open: true,
})
});
Существует ряд библиотек, которые также предлагают помощники неизменяемости для внесения изменений в обычные изменяемые объекты.
React уже давно имеет встроенный набор помощников неизменяемости. Они используют синтаксис, аналогичный запросам MongoDB.
import update from 'react-addons-update';
return update(state, {
notificationBar: {
open: { $set: true }
}
});
Эта библиотека позволяет использовать знакомые пути точек для указания обновлений (вложенных) свойств.
import dotProp from 'dot-prop-immutable';
return dotProp.set(state, 'notificationBar.open', true);
Эта библиотека является оберткой вокруг react-addons-update
и предоставляет более функциональный синтаксис для обновления (вложенных) свойств.
Вместо того, чтобы передавать новое значение, вы передаете функцию, которая принимает старое значение и возвращает новое.
import updateIn from 'update-in';
return updateIn(state, ['notificationBar', 'open'], () => true);
Для обновления свойств эта библиотека похожа на нечто среднее между dot-prop-immutable
и update-in
.
import path from 'immutable-path';
return path.map(state, 'notificationBar.open', () => true);