首页 > 解决方案 > 呈现 JSX 的函数与在另一个组件中声明组件的函数有什么区别?

问题描述

这是反模式吗?

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 中制作 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>
    );
}

编辑:

如何在本地创建组件/渲染函数,调用一次?

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

    return (
        <form>
            <input />
            {renderButton(props.isDone)}
        </form>
    );
}

标签: reactjsreact-hooksjsxreact-functional-component

解决方案


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

// #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 执行协调过程,因为您需要尽可能多地渲染静态树。

最简单的解决方案是将功能/功能组件移动到外部范围或将逻辑内联到树本身。

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>
  );
}

像这样渲染项目有什么区别

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


推荐阅读