传递 ReactElement 和传递 returns ReactElement 的函数之间的区别
Difference between passing a ReactElement and a function that returns a ReactElement
将 ReactElement
传递为 属性 有什么区别:
<RenderParam ReactElement={<Counter />} />
function RenderParam({ ReactElement }) {
return <div>{ReactElement}</div>;
}
并传递一个函数 returns 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)
- 第二种情况也会在每次父组件渲染时丢失其状态。
我看不出它们之间有什么区别。为什么第一个案例能够保持其状态?
这个其实很简单,真正的是渲染本身的时间。
让我们从第二种情况开始,这实际上是一种称为Render Props的设计模式,您可以在这里阅读:https://reactjs.org/docs/render-props.html
在这种情况下,prop 包含一个 returns 一个 React 元素的函数,这意味着只有当您调用该函数时才会对其进行评估,因此它并不总是像第一种情况那样 "alive"。
第一种情况:当您将 prop 绑定到 Element 时,它会在创建父元素时进行评估。这意味着只要父元素是 "alive",prop 元素就会存在。
第一个示例将静态 JSX 元素 <Counter />
作为 RenderParam
属性传递。第二个例子使用了一个函数 instantiatedCounter
,它允许 return 一个更动态的 JSX 元素,通常被称为 Render props.
在第二种情况下,你会丢失状态,因为 React 每次都将 ReactElement
prop 视为新定义的组件,卸载旧组件并在每个渲染周期重新安装它。你想要做的是 调用 ReactElement
属性来检索 JSX 元素作为 return 值:
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} />
}
将 ReactElement
传递为 属性 有什么区别:
<RenderParam ReactElement={<Counter />} />
function RenderParam({ ReactElement }) {
return <div>{ReactElement}</div>;
}
并传递一个函数 returns 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)
- 第二种情况也会在每次父组件渲染时丢失其状态。
我看不出它们之间有什么区别。为什么第一个案例能够保持其状态?
这个其实很简单,真正的是渲染本身的时间。
让我们从第二种情况开始,这实际上是一种称为Render Props的设计模式,您可以在这里阅读:https://reactjs.org/docs/render-props.html 在这种情况下,prop 包含一个 returns 一个 React 元素的函数,这意味着只有当您调用该函数时才会对其进行评估,因此它并不总是像第一种情况那样 "alive"。
第一种情况:当您将 prop 绑定到 Element 时,它会在创建父元素时进行评估。这意味着只要父元素是 "alive",prop 元素就会存在。
第一个示例将静态 JSX 元素 <Counter />
作为 RenderParam
属性传递。第二个例子使用了一个函数 instantiatedCounter
,它允许 return 一个更动态的 JSX 元素,通常被称为 Render props.
在第二种情况下,你会丢失状态,因为 React 每次都将 ReactElement
prop 视为新定义的组件,卸载旧组件并在每个渲染周期重新安装它。你想要做的是 调用 ReactElement
属性来检索 JSX 元素作为 return 值:
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} />
}