渲染 JSX 的函数与在另一个组件内声明组件的函数有什么区别?
What's the difference between functions that render JSX vs. declaring components inside another component?
这是反模式吗?
export function Todo() {
...
const renderItem = (item) => (
item.done
? <strike>{item.text}</strike>
: <span>{item.text}</span>
);
return (
<ul>
{items.map((item) => <li>renderItems(item)</li>)}
</ul>
);
}
与在 Todo 中制作项目组件相比,这样渲染项目有什么区别,例如:
export function Todo() {
...
const Item = (props) => (
props.item.done
? <strike>{item.text}</strike>
: <span>{item.text}</span>
);
return (
<ul>
{items.map((item) => <li><Item item={item} /></li>)}
</ul>
);
}
编辑:
如何在本地创建 components/render 个调用一次的函数?
export function SomeForm(props) {
const renderButton = (isComplete) => (
isComplete
? <button>Submit</button>
: <button disabled>Please complete</button>
);
return (
<form>
<input />
{renderButton(props.isDone)}
</form>
);
}
事先让我们将示例修复为有效代码:
// #1
export function Todo({items}) {
const renderItem = (item) =>
item.done ? <strike>{item.text}</strike> : <span>{item.text}</span>;
return (
<ul>
{items.map((item) => (
<li key={item.id}>{renderItems(item)}</li>
))}
</ul>
);
}
// #2
export function Todo({items}) {
const Item = (props) =>
props.item.done ? <strike>{item.text}</strike> : <span>{item.text}</span>;
return (
<ul>
{items.map((item) => (
<li key={item.id}>
<Item item={item} />
</li>
))}
</ul>
);
}
回到问题,是的那些是反模式。
为什么它是反模式?
在这两个示例中,即使没有任何视觉变化,您也将重新呈现项目。
原因是在每次渲染时,您都会重新创建函数 (renderItem
) 和函数组件 (Item
)。
你想要什么
相反,您想让 React 执行 Reconciliation 过程,为此您需要尽可能多地渲染静态树。
最简单的解决方案就是将 function/function 组件移动到外部范围或将逻辑内联到树本身。
const renderItem = (item) => (...)
const Item = (props) => (...)
export function Todo({ items }) {
return (
<ul>
{items.map((item) => (
<li key={item.id}>
(item.done ? <strike>{item.text}</strike>:<span>{item.text}</span>)
</li>
))}
</ul>
);
}
What's the difference between rendering items like that
renderItem
只是一个返回 JSX 的函数,Item
是一个 React 组件,因此它的状态被注册到 React 树(“只是一个函数”不能保持自己的状态) .
这是反模式吗?
export function Todo() {
...
const renderItem = (item) => (
item.done
? <strike>{item.text}</strike>
: <span>{item.text}</span>
);
return (
<ul>
{items.map((item) => <li>renderItems(item)</li>)}
</ul>
);
}
与在 Todo 中制作项目组件相比,这样渲染项目有什么区别,例如:
export function Todo() {
...
const Item = (props) => (
props.item.done
? <strike>{item.text}</strike>
: <span>{item.text}</span>
);
return (
<ul>
{items.map((item) => <li><Item item={item} /></li>)}
</ul>
);
}
编辑:
如何在本地创建 components/render 个调用一次的函数?
export function SomeForm(props) {
const renderButton = (isComplete) => (
isComplete
? <button>Submit</button>
: <button disabled>Please complete</button>
);
return (
<form>
<input />
{renderButton(props.isDone)}
</form>
);
}
事先让我们将示例修复为有效代码:
// #1
export function Todo({items}) {
const renderItem = (item) =>
item.done ? <strike>{item.text}</strike> : <span>{item.text}</span>;
return (
<ul>
{items.map((item) => (
<li key={item.id}>{renderItems(item)}</li>
))}
</ul>
);
}
// #2
export function Todo({items}) {
const Item = (props) =>
props.item.done ? <strike>{item.text}</strike> : <span>{item.text}</span>;
return (
<ul>
{items.map((item) => (
<li key={item.id}>
<Item item={item} />
</li>
))}
</ul>
);
}
回到问题,是的那些是反模式。
为什么它是反模式?
在这两个示例中,即使没有任何视觉变化,您也将重新呈现项目。
原因是在每次渲染时,您都会重新创建函数 (renderItem
) 和函数组件 (Item
)。
你想要什么
相反,您想让 React 执行 Reconciliation 过程,为此您需要尽可能多地渲染静态树。
最简单的解决方案就是将 function/function 组件移动到外部范围或将逻辑内联到树本身。
const renderItem = (item) => (...)
const Item = (props) => (...)
export function Todo({ items }) {
return (
<ul>
{items.map((item) => (
<li key={item.id}>
(item.done ? <strike>{item.text}</strike>:<span>{item.text}</span>)
</li>
))}
</ul>
);
}
What's the difference between rendering items like that
renderItem
只是一个返回 JSX 的函数,Item
是一个 React 组件,因此它的状态被注册到 React 树(“只是一个函数”不能保持自己的状态) .