Как я могу предотвратить реакцию 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), то Реакция "снесет старое дерево и построит новое дерево с нуля".

Чтобы предотвратить это, вам нужно использовать один и тот же компонент для обоих маршрутов.

Ответ 3

Вы можете использовать shouldComponentUpdate и, если маршрут изменился с /edit на /edit/:id (вы можете проверить это получение информация о маршрутизаторе из состояния, подключенного к вашему компоненту) возвращает false, поэтому он не обновляет компонент.