jun*_*lin 19 javascript reactjs
function renderSomething(foo) {
return <div>sth {foo}</div>
}
function Something({ foo }) {
return <div>sth {foo}</div>
}
function Component(props) {
const { foo } = props
return (
<>
{renderSomething(foo)}
<Something foo={foo} />
</>
)
}
Run Code Online (Sandbox Code Playgroud)
renderSomething()
和的 JSX 结果<Something />
是相同的。我想知道这两种方式之间有什么区别(例如渲染方式、行为、影响等)?
render方法(即)适用于什么场景renderSomething()
?我可以在里面使用挂钩吗?
T.J*_*der 31
renderSomething()
和的 JSX 结果<Something />
是相同的。
renderSomething(foo)
做<Something foo={foo} />
完全不同的事情,但在特定的用法中,最终结果是相同的:React 创建一个 React 元素,告诉它稍后渲染div
(如果使用该元素)。DoingrenderSomething(foo)
就像renderSomething
一个钩子,它会影响你在它运行时如何使用它。
以下是两个主要区别:
使用renderSomething(foo)
,您的代码将立即调用该函数并传入参数。有了<Something foo={foo} />
,你就不用打电话了Something
。您要求 React 记住它,并在以后需要渲染您执行这些调用的组件时调用它。
因为你的代码(而不是 React)调用renderSomething
,如果你在其中使用了钩子,它们会将信息放入调用组件的实例和状态信息中。相反,如果Something
使用钩子,则该实例和状态信息将存储在其自身的组件实例中Something
。
(还有其他差异。您不能将renderSomething
via 用作组件<renderSomething foo={foo} />
,因为函数组件名称必须以大写字母开头,以区别于 HTML 元素,并且renderSomething
需要字符串参数,而不是 props 对象。)
让我们更仔细地看看其中的一些差异:
function renderSomething(foo) {
console.log(`renderSomething: Called with foo = ${foo}`);
return <div>sth {foo}</div>;
};
function Something({ foo }) {
console.log(`Something: Called with foo prop = ${foo}`);
return <div>sth {foo}</div>;
}
console.log(`Creating elements via renderSomething("x"):`);
const ex1 = renderSomething("x");
console.log(`Creating elements via <Something foo="x" />:`);
const ex2 = <Something foo="x" />;
console.log(`Done`);
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
Run Code Online (Sandbox Code Playgroud)
请注意,代码调用了 renderSomething
(您看到它console.log
发生了),但没有调用Something
(您看不到它console.log
)。这是因为上面的差异#1。关键是组件的函数只有在需要渲染时才会被调用。我们没有渲染上面的任何结果,因此该函数永远不会被调用。
第二个区别更微妙,但让我们假设两件事:
Example
)可能需要也可能不需要渲染它。这适用于Something
:
const { useState, useEffect } = React;
function Something({ foo }) {
const [thing, setThing] = useState(null);
useEffect(() => {
setTimeout(() => { // Fake ajax
setThing("thing");
}, 100);
}, []);
return <div>foo = {foo}, thing = {thing}</div>;
}
function App() {
const [foo, setFoo] = useState("");
return <div>
<div>
<label>
<input type="checkbox" checked={!!foo} onChange={() => setFoo(foo => foo ? "" : "hi")} />
Toggle "foo"
</label>
{foo ? <Something foo={foo} /> : null}
</div>
</div>;
}
ReactDOM.render(<App />, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)
label {
user-select: none;
}
Run Code Online (Sandbox Code Playgroud)
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
Run Code Online (Sandbox Code Playgroud)
但现在让我们尝试一下renderSomething
:
const { useState, useEffect } = React;
function renderSomething(foo) {
const [thing, setThing] = useState(null);
useEffect(() => {
setTimeout(() => { // Fake ajax
setThing("thing");
}, 100);
}, []);
return <div>foo = {foo}, thing = {thing}</div>;
}
function App() {
const [foo, setFoo] = useState("");
return <div>
<div>
<label>
<input type="checkbox" checked={!!foo} onChange={() => setFoo(foo => foo ? "" : "hi")} />
Toggle "foo"
</label>
{foo ? renderSomething(foo) : null}
</div>
</div>;
}
ReactDOM.render(<App />, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)
label {
user-select: none;
}
Run Code Online (Sandbox Code Playgroud)
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
Run Code Online (Sandbox Code Playgroud)
当您勾选带有此错误的框时,它会爆炸:
警告:React 检测到 App 调用的 Hook 顺序发生了变化。如果不修复,这将导致错误和错误。有关更多信息,请阅读 Hooks 规则:https://reactjs.org/link/rules-of-hooks 上一个渲染 下一个渲染 -------------------------------------------------- ---- 1. useState 使用状态 2. 未定义的useState ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ 在应用程序 (<匿名>:35:22)
renderSomething
这是因为当我们没有在第一次渲染时调用它时,就会调用代码。这是因为上面的#2:由于renderSomething
不是组件函数,因此它不会获得自己的组件实例,并且对其中的钩子的任何调用就像对父组件(Example
)中的钩子的调用一样。但函数组件有时不允许调用钩子,有时则不允许。这是因为React 依赖于调用钩子的顺序,并且该顺序必须保持一致才能进行钩子管理。同样,renderSomething
像这样使用renderSomething
就是用作钩子(这正是自定义钩子的工作方式,最终调用内置钩子,然后将信息存储在父实例中)。
正如您所看到的,虽然您在示例中得到的结果是相同的,但总的来说它们是完全不同的东西。:-)
归档时间: |
|
查看次数: |
4830 次 |
最近记录: |