Как я могу предотвратить реакцию React на размонтирование/восстановление компонента?
Я использую react-router
и react-redux
. У меня есть два маршрута:
<Route path='/edit' component={ EditNew } />
<Route path='/edit/:id' component={ EditDraft } />
где EditNew
и EditDraft
- контейнеры, предоставляющие данные, которые обертывают компонент Editor
, используя функцию react-redux
connect
:
const EditNew = connect(state => ({}))(React.createClass({
render() {
return <Editor />;
}
}));
и
const EditDraft = connect(state => ({ drafts: state.drafts }))(React.createClass({
render() {
const { params, drafts } = this.props;
const draft = findDraft(params.id, drafts);
return <Editor draft={ draft } />;
}
}));
Теперь Editor
скомпонован таким образом, что когда вы начинаете вводить пустой пробел Editor
, он запускает history.replaceState()
от /edit
до /edit/:id
с помощью сгенерированного сгенерированного идентификатора. Когда это произойдет, я получаю следующую последовательность событий:
-
EditorNew
отключает
-
Editor
unmounts
-
EditorDraft
отображает и монтирует
-
Editor
отображает и монтирует
Когда я закодировал эти два контейнера, я подумал, что компонент Editor
, содержащийся в обоих из них, будет сверяться без размонтирования и повторной установки. Это проблема для меня по нескольким причинам, помимо лишней ненужной работы, главным из которых является то, что редактор заканчивает потерять фокус и правильный диапазон курсора после размонтирования и повторного подключения.
Безрезультатно, я попытался указать key
для компонента Editor
, чтобы намекнуть на систему согласования, что он тот же компонент, и я пробовал shouldComponentUpdate
, но это не вызвано, что делает с учетом того, что Реакт делает.
Помимо объединения двух контейнеров в один контейнер с более сложной логикой render()
, могу ли я что-нибудь сделать, чтобы предотвратить отключение/переустановку компонента Editor
во время перехода истории?
Ответы
Ответ 1
Реагирует алгоритм согласования говорит, что если элемент имеет другой тип (в данном случае EditNew
и EditDraft
), то Реакция "снесет старое дерево и построит новое дерево с нуля".
Чтобы предотвратить это, вам нужно использовать один и тот же компонент для обоих маршрутов.
Ответ 2
Скорее всего, это невозможно при react-router
<= v3.
С react-router
v4 это должно быть возможно сейчас: https://github.com/ReactTraining/react-router/issues/4578
Ответ 3
Вы можете использовать shouldComponentUpdate
и, если маршрут изменился с /edit
на /edit/:id
(вы можете проверить это получение информация о маршрутизаторе из состояния, подключенного к вашему компоненту) возвращает false, поэтому он не обновляет компонент.