2

ReactElement将 a作为属性传递有什么区别:

第一个案例

<RenderParam ReactElement={<Counter />} />

function RenderParam({ ReactElement }) {
  return <div>{ReactElement}</div>;
}

并传递一个返回 a 的函数ReactElement

第二种情况

const instantiatedCounter = () => <Counter />; 

<RenderParam ReactElement={instantiatedCounter} />

function RenderParam({ ReactElement }) {
  return <div> <ReactElement /> </div> 
}

我看到生命周期存在差异:

  • 每次父 react 元素更新时,Counter都会执行第二种情况的挂载循环:
ReactElement changed (at RenderParam lifecycle)
component did mount (at Counter)
  • 每次父组件渲染时,第二种情况也会丢失其状态。

我看不出它们之间有什么区别。为什么第一个案例能够保持其状态?

4

2 回答 2

2

这实际上相当简单,这里真正的事情是渲染本身的时间。

让我们从第二种情况开始,这实际上是一种称为 Render Props 的设计模式,您可以在这里阅读:https ://reactjs.org/docs/render-props.html 在这种情况下,prop 包含一个返回的函数一个 React 元素,这意味着它只会在你调用该函数时被评估,因此它并不总是像你的第一种情况那样“活着”。

第一种情况:当您将道具绑定到元素时,它会在创建父元素时进行评估。这意味着只要父元素“活着”,道具元素就会活着。

于 2020-02-16T12:33:59.797 回答
2

第一个示例将静态 JSX 元素<Counter />作为RenderParamprop 传递。第二个示例使用一个函数instantiatedCounter,它允许返回一个更动态的 JSX 元素,通常称为Render props

在第二种情况下,您会丢失状态,因为 ReactReactElement每次都将 prop 视为新定义的组件,卸载旧组件并在每个渲染周期再次安装它。您要做的是调用propReactElement来检索 JSX 元素作为返回值:

function RenderParam({ ReactElement }) {
  return <div>{ReactElement()}</div>; 
  // not: return <div><ReactElement /></div>
}

您也可以使用 JSX 语法来定义它<div><ReactElement /></div>。但是请确保instantiatedCounter它是一个静态函数,并且不会在每次渲染时重新创建,因此对象引用保持不变:

const instantiatedCounter = () => <Counter />; 
// make it static in some way, so object reference doesn't change

export default function App() {
  // .. and remove instantiatedCounter here
  return <RenderParam ReactElement={instantiatedCounter} />
}
于 2020-02-16T13:33:30.440 回答