2016-01-15 4 views
1

В issue 303 в репозитории Redux Дан Абрамов дает пример функции, которая может обернуть метод subscribe магазина, чтобы передать предыдущее состояние подписчику.Сравнить предыдущее состояние

function observeStore(store, select, onChange) { 
    let currentState; 

    function handleChange() { 
    let nextState = select(store.getState()); 
    if (nextState !== currentState) { 
     currentState = nextState; 
     onChange(currentState); 
    } 
    } 

    let unsubscribe = store.subscribe(handleChange); 
    handleChange(); 
    return unsubscribe; 
} 

По какой-то причине это не работает для меня. В первый раз мой onChange обработчик называется currentState - undefined, как и следовало ожидать. Однако при каждом последующем изменении состояния свойства currentState эквивалентны по значению (==) значениям nextState. Два объекта состояния не являются одним и тем же объектом, хотя из-за того, что nextState === currentState оценивает false.

Скорее всего, у меня что-то действительно очевидное. Как захватить предыдущее состояние в закрытии?

+0

'==' не является «эквивалентностью по значению». Вы можете легко проверить, что '{}! = {}'. См. Также: http://stackoverflow.com/questions/359494/does-it-matter-which-equals-operator-vs-i-use-in-javascript-comparisons – mik01aj

+0

То, что я пытался передать, состоит в том, что два состояния являются определенно разными объектами ('! =='), но свойство, которое я изменил, равно в двух экземплярах. Это похоже на то, что наблюдатель видит две копии обновленного состояния, а не старое и новое состояние. –

+0

Argh! Я должен делать что-то еще неправильно в моем приложении, потому что http://jsbin.com/xebomi/edit?js,console иллюстрирует, что он работает. (Ну, с одной модификацией оригинального кода Дэна.) –

ответ

2

Проблема в том, что мой редуктор фактически не создавал новый экземпляр состояния, т. Е. Я искажал состояние на месте, а не возвращал новую копию. Мой редуктор код был что-то вроде:

const newState = Object.assign({}, state); 
newState.my.prop = …; 
return newState; 

Однако Object.assign и ES2015 деструктурирующего задания только делать мелких копий, то есть они влияют только на один уровень. В моем приложении состояние, которое я обновлял, было на три уровня. Я использовал быстрый, грязный, некрасивый хак в моем редукторе, чтобы проверить мою теорию:

const newState = JSON.parse(JSON.stringify(state)); // <-- Yuck! 
newState.my.prop = …; 
return newState; 

Не попробовать, что у себя дома. Это был мой первый ключ. Правильная реализация будет использовать что-то вроде библиотеки Facebook Immutable, чтобы гарантировать, что каждая мутация приведет к новому клону.

+0

В редукторах вы также можете использовать [Помощники по нестабильности] (https://facebook.github.io/react/docs/update.html) без необходимости использования неизменяемых js во всем проекте – antiplayer

+0

Я просто сгорел из-за мутации состояния. Мне нужна глубокая заморозка (npm), чтобы найти проблему. –

Смежные вопросы