2016-04-06 6 views
2

Пожалуйста, обратитесь к следующей функции для этого вопроса:Redux не повторный рендеринг, когда вложенный объект обновляется

const mapStateToProps = (state) => { 
    return { 
    currentPlaylist: state.currentPlaylist, 
    currentSong: state.currentSong, 
    localPlaylists: state.playlistsBySource['local'], 
    videoSize: state.videoSize, 
    }; 
} 

Это mapStateToProps функции для контейнера. Я ожидал, что компонент, подключенный к этому контейнеру, будет повторно отображаться каждый раз, когда обновляется state.playlistsBySource['local']. Однако, это не оказало даже если state.playlistsBySource['local'] обновляется, поэтому я изменил код ниже:

const mapStateToProps = (state) => { 
    return { 
    currentPlaylist: state.currentPlaylist, 
    currentSong: state.currentSong, 
    playlists: state.playlistsBySource, 
    videoSize: state.videoSize, 
    }; 
} 

Тогда связная компонента правильно обновляется каждый раз, когда state.playlistsBySource['local'] была обновлена. Но это своего рода отходы, потому что подключенный компонент не нужен весь playlists.

Почему это происходит именно так, и каков правильный способ его решения?

Update

подключить компонент, как это:

export default connect(
    mapStateToProps, 
    mapDispatchToProps 
)(DumbComponent); 

Метод визуализации DumbComponent не дозвонились, когда state.playlistsBySource['local'] был обновлен в глобальном хранилище.

UPDATE2: Редуктор кажется неизменным .. я чего-то не хватает?

case CONSTANTS.UPDATE_LOCAL_PLAYLIST: 
    var playlistUpdated = transformedPlaylist(state[action.playlist.source], action); 
    return updatedPlaylists(playlistUpdated, state); 

function transformedPlaylist(state=[], action) { 
    var oldPlaylist = _.find(state, (pl) => 
    pl.playlistName === action.playlist.playlistName); 

    switch (action.type) { 
    case CONSTANTS.RECEIVE_PLAYLIST: 
    case CONSTANTS.UPDATE_LOCAL_PLAYLIST: 
     return Object.assign({}, oldPlaylist, action.playlist, { 
     isFetching: false, 
     }); 
    default: 
     return oldPlaylist 
    } 
} 

function updatedPlaylists(playlistUpdated, oldPlaylists) { 
    const source = playlistUpdated.source; 
    const idxToUpdate = _.findIndex(oldPlaylists[source], (pl) => 
    pl.playlistName === playlistUpdated.playlistName 
); 
    var playlists = Object.assign({}, oldPlaylists); 
    playlists[source][idxToUpdate] = playlistUpdated; 
    return playlists; 
} 
+0

Когда вы говорите «компонент, подключенный к этому контейнеру», вы имеете в виду компонент, который отображается этим контейнером? или просто, что метод визуализации этого связанного компонента реакции не вызывается, когда в хранилище обновляется 'state.playlistsBySource.local'? – ZekeDroid

+0

@ZekeDroid Я обновил вопрос. Я думаю, что это то, что я имел в виду. –

ответ

4

Это поможет, если вы могли бы разместить соответствующий код для редуктора. Тем не менее, подавляющее большинство времени, причина, по которой ваш компонент не обновляется, заключается в том, что вы непосредственно изменяете состояние в своем редукторе, а не постоянно меняете измененные копии. Дополнительную информацию см. В ответе на вопросы Redux по телефону http://redux.js.org/docs/FAQ.html#react-not-rerendering.

Update:

Эта линия выглядит подозрительно: playlists[source][idxToUpdate] = playlistUpdated;

Помните, что при обновлении вложенных данных непреложно, вы должны вернуть скопирована и обновленные элементы вплоть до верхней части данных ,

Трудно сказать точно, не видя всю свою структуру состояния и действия в контексте, но я думаю, что довольно вероятно, что вы действительно выполняете прямую мутацию в одном из ваших вложенных полей.

+0

Пожалуйста, см. Мое обновление –

+0

Строка прямо над ней 'var playlists = Object.assign ({}, oldPlaylists);' думал. Разве это не делает его неизменным? –

+1

Это мелкая копия. Он копирует поля объекта верхнего уровня, но эти поля по-прежнему указывают на одни и те же вложенные данные. Итак, если вы напрямую пишете вложенный объект, вы напрямую его мутировали. – markerikson

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