【问题标题】:Preserving React DOM elements' native state during a transplant在移植期间保留 React DOM 元素的原生状态
【发布时间】:2018-03-03 09:55:45
【问题描述】:

我正在使用 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>
)

它从头开始重新创建 &lt;input/&gt; DOM 元素,并且它的所有浏览器原生状态都丢失了,尽管 key= 保持不变!

这里是 a codepen 演示出了什么问题。您的打字在“之前”和“之后”之间保持不变,但在“内部”中消失。


这是 React 的基本限制,还是有一种适当的方法可以在父母之间移动时保持原生元素的完整性?

【问题讨论】:

    标签: javascript reactjs html-input


    【解决方案1】:

    key 属性用于区分对等组件。假设不同上下文中的组件不具有可比性。例如,

    <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

    【讨论】:

    • 呸,面包屑!这个.focus 的把戏发挥了作用……但不是真的。它会杀死移动设备上的触摸键盘,丢失用户的精确选择,并使用输入重置任何第三方(非反应)工具。 如果这真的是 React 能做的最好的事情,请让我失望。 :-(
    【解决方案2】:

    您的观察是正确的,当您将输入元素放入新容器时,react 会创建一个新的虚拟 DOM 节点并重新渲染其子节点。当你简单地将一堆元素放在相同的深度时,react 会根据 key prop 跟踪每个元素的顺序,并且只对元素进行重新排序,而不需要完整的重新渲染。虽然我不知道为什么要在重新编码时将元素放入容器中,但您可以将状态存储在组件的状态中并相应地传递它。如果状态以某种方式无法保存到状态。您应该为元素找到一个共同的层次结构,例如,将每个输入包装在一个容器中,并将键分配给容器而不是输入。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-20
      • 2018-06-22
      • 2020-12-28
      • 1970-01-01
      • 1970-01-01
      • 2021-08-05
      • 2018-09-10
      • 2011-12-15
      相关资源
      最近更新 更多