渲染 JSX 的函数与在另一个组件内声明组件的函数有什么区别?

wra*_*him 6 jsx reactjs react-hooks react-functional-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>
    );
}
Run Code Online (Sandbox Code Playgroud)

与在 Todo 中创建 Item 组件相比,渲染这样的项目有什么区别,如下所示:

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>
    );
}
Run Code Online (Sandbox Code Playgroud)

编辑:

在本地创建被调用一次的组件/渲染函数怎么样?

export function SomeForm(props) {
    const renderButton = (isComplete) => (
        isComplete
            ? <button>Submit</button>
            : <button disabled>Please complete</button>
    );

    return (
        <form>
            <input />
            {renderButton(props.isDone)}
        </form>
    );
}
Run Code Online (Sandbox Code Playgroud)

Den*_*ash 13

首先让我们将示例修复为有效的代码:

// #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>
  );
}
Run Code Online (Sandbox Code Playgroud)

回到问题,是的,这些是反模式。

为什么它是反模式?

在这两个示例中,即使没有任何视觉变化,您也将重新渲染该项目。

其原因是在每次渲染时,您都会重新创建函数 ( renderItem) 和函数组件 ( Item)。

你想要什么

相反,您想让 React 执行协调过程,因为您需要尽可能多地渲染静态树。

最简单的解决方案是将函数/函数组件移动到外部作用域或将逻辑内联到树本身中。

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>
  );
}
Run Code Online (Sandbox Code Playgroud)

类似的渲染项目有什么区别

renderItem只是一个返回 JSX 的函数,Item是一个 React 组件,因此它的状态被注册到 React 树(“只是一个函数”不能保存自己的状态)。