Сохранение исходного состояния элементов React DOM во время трансплантации

Я работаю с React, чтобы создать подобный форме интерфейс, вы знаете, с различными <input/> элементы и тому подобное. Одна из особенностей заключается в том, что текстовые поля упорядочиваются и перестраиваются из-за других данных (с сервера или других входных данных)...

React хорошо справляется со всеми изменениями, за исключением одного случая: перемещение элемента между родителями.

мой render() JSX может переключаться между следующими в зависимости от состояния:

return (
    <div className="parent">
        <h4>Before container</h4>

        <input type="text" key="one"/>
        <div className="container"/>
    </div>
)

А также:

return (
    <div className="parent">
        <h4>After container</h4>

        <div className="container"/>
        <input type="text" key="one"/>
    </div>
)

Это все работает просто отлично - ввод перемещается и сохраняет все свое родное состояние браузера (фокус / введенный в настоящее время текст / выделение / и т. Д.).

Но когда он переключается на:

return (
    <div className="parent">
        <h4>Inside container</h4>

        <div className="container">
            <input type="text" key="one"/>
        </div>
    </div>
)

Это воссоздает <input/> Элемент DOM с нуля и все его нативное состояние браузера теряется, несмотря на сохранение key= нетронутый!

Вот кодекс, демонстрирующий, что идет не так. Ваш набор текста остается неизменным, перемещаясь между "до" и "после", но умирает "внутри".


Является ли это фундаментальным ограничением React или существует правильный способ сохранить нативный элемент в целости при перемещении между родителями?

2 ответа

key prop предназначен для разграничения между равноправными компонентами. Предполагается, что компоненты в разных контекстах не сопоставимы. Например,

<div className="parent">
    <h4>Before and After container</h4>

    <input type="text" key="one"/>
    <div className="container"/>
    <input type="text" key="one"/>
</div>

Вызовет проблемы, но;

<div className="parent">
    <h4>Before and Inside container</h4>

    <input type="text" key="one"/>
    <div className="container">
        <input type="text" key="one"/>
    </div>
</div>

будет хорошо.

Итак, как мы решаем проблему?

Лучше всего назначить ссылку на поле ввода, а затем перефокусировать ее после каждого обновления;

<input type="text" key="one" ref={(input) => { this.textInput = input; }}/>

а потом

componentDidUpdate() {
    this.textInput.focus();
}

обновленная кодовая ручка: https://codepen.io/anon/pen/eGdmeV

РЕДАКТИРОВАТЬ:

Принимая во внимание, что вам действительно нужна встроенная поддержка из-за других ваших инструментов, лучшим способом может быть просто обеспечить согласованную иерархию;

<div className="parent">
    <h4>Before container</h4>
    <div key="oneContainer">
        <input type="text" key="one"/>
    </div>
    <div className="container"/>
</div>


<div className="parent">
    <h4>After container</h4>
    <div className="container"/>
    <div key="oneContainer">
        <input type="text" key="one"/>
    </div>
</div>



<div className="parent">
    <h4>Inside container</h4>
    <div className="container" key="oneContainer">
        <input type="text" key="one"/>
    </div>
</div>

Codepen: https://codepen.io/anon/pen/bowNKB

Ваше наблюдение верно, когда вы помещаете элемент ввода в новый контейнер, реагирует, создает новый виртуальный узел DOM и повторно отображает его дочерние элементы. Когда вы просто размещаете группу элементов на одной и той же глубине, реагирование отслеживает порядок каждого элемента на основе ключевого элемента и только переупорядочивает элемент без полного повторного отображения. Хотя я понятия не имею, почему вы хотите поместить элемент в контейнер при повторном кодировании, вы можете сохранить состояние в состоянии компонента и передать его соответствующим образом. Если состояние как-то не может быть сохранено в состояние. Вы должны найти общую иерархию для элементов, например, обернуть каждый вход в контейнере и назначить ключ для контейнеров вместо входов.

Другие вопросы по тегам