【问题标题】:Refs preserved with React.cloneElement()使用 React.cloneElement() 保存的 Refs
【发布时间】:2019-07-03 13:08:37
【问题描述】:

我不明白React official docs 中写的陈述的重点:

cloneElement()

React.cloneElement(
  element,
  [props],
  [...children]
)

使用 element 作为起点克隆并返回一个新的 React 元素。结果元素将具有原始元素的道具和新道具的浅层合并。新的孩子将取代现有的孩子。原始元素的 key 和 ref 将被保留。

React.cloneElement() 几乎等同于:

<element.type {...element.props} {...props}>{children}</element.type>

但是,它也保留了 refs。这意味着如果你得到一个带有 ref 的孩子,你不会不小心从你的祖先那里偷走它。您将获得附加到新元素的相同 ref。

让我感到困惑的是声明 这意味着如果你得到一个带有 ref 的孩子,你不会不小心从你的祖先那里偷走它。您将获得附加到新元素的相同 ref。

如果我理解好的,即使 Parent 被克隆,指向 Parent 组件中 Child 元素的 ref 也会被保留。所以在React.cloneElement(Parent) 之后,有两个单独的Parents(内部具有相同的深度值,包括ref),并且都分别具有refs,并且这些refs 指向同一个Child。我说的对吗?

那么祖先有什么用呢?这种情况下的祖先是什么?

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    为了给您举例说明文档似乎说明了什么,让我们考虑一个组件 App,它呈现一个组件 Main 并且它有两个子 Home 和 Dashboard 并为其指定了 refs

    class App extends React.Component {
       constructor(props) {
          super(props);
          this.homeRef = React.createRef();
          this.dashboardRef = React.createRef();
       }
       render() {
          return (
              <Main>
                   <Home ref={this.homeRef} key={'Home'}/>
                   <Dashboard ref={this.dashboardRef} key={'Dashboard'}/>
              </Main>
          )         
       }
    }
    

    现在主组件克隆子元素为其子元素添加一个道具 onClick,

    class Main extends React.Component {
       onClick = () => {}
       render() {
           return (
              <div>
                  {/* Some content here */}
                  {React.Children.map(this.props.children, child => {
                     return React.cloneElement(child, {onClick: this.onClick})
                   })}
              </div>
           )
       }
    }
    

    现在当Main 组件克隆子组件时

    React.cloneElement(child, {onClick: this.onClick})
    

    在我们的例子中是 Home 和 Dashboard 组件,如果 cloneElement 忽略 App 组件传递给它们的 keyref,则 App 组件将无法访问它的这些子组件呈现。因此 React.cloneElement 保留了传递给元素的 ref 和键,即使它们在子渲染函数中被克隆。

    createdElement创建的组件是clone child,什么是 &lt;Main&gt; 使用的是克隆的孩子,那么&lt;App&gt; 中的 ref 是什么意思? 原始孩子,还是克隆孩子?

    “意外偷窃”这个短语是否意味着禁止之类的意思? 访问

    仅当元素在 DOM 中呈现时,对元素的引用才有意义。在上述情况下,原始元素不会被渲染,但克隆的元素会被渲染。如果 React 没有为在 DOM 中呈现的克隆组件分配相同的 ref,App 组件将不会与任何重要的交互。此外,如果您决定渲染原始子代和克隆的子代,则 ref 将指向克隆的子代。

    Demo illustrating the above

    P.S. CloneElement 不用于克隆组件,而不是渲染 JSX 实例,主要用于向

    从其他地方渲染的子组件

    我希望上面的例子能解释这个场景

    【讨论】:

    • 感谢您的友好解释。 React.cloneElement 的想法我差不多知道了,但是这里还是有一些疑问: 1.createdElement创建的组件被克隆child&lt;Main&gt;使用的是cloned child,那是什么ref&lt;App&gt; 点?原始孩子,还是克隆孩子?如果ref 指向original child,那么这两个Children 是否等价,只是它们有不同的道具(是否有onClick)?
    • 2.我仍然不明白文档中的声明:你不会不小心从你的祖先那里偷走它。短语意外窃取是否意味着禁止访问?要理解完整的句子,是否意味着我可以通过正确的方式而不是禁止的方式获得 ref for child
    • 用演示和更多解释更新了我的答案
    • 您提供的演示非常清楚。关键部分是In the above case the original element is not rendered but the cloned element is。感谢您的详细解释。
    • 很好的演示。可以通过让 HomeDashboard 组件将 onClick 属性附加到它们的 div 来改进它。这将表明单击克隆的子项会触发onClick,但原始子项不会。
    猜你喜欢
    • 2017-06-12
    • 2018-07-16
    • 2018-08-01
    • 2016-07-30
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    • 2018-05-27
    • 2019-07-22
    相关资源
    最近更新 更多