函数组件中的函数应该去哪里?

2022-08-30 02:24:44

我试图将我在这里找到的这个很酷的动画转换为React可重用的组件。看起来此组件需要一个父组件作为画布,许多子组件用于 。<canvas>function Ball()

出于性能原因,将组件制作成无状态组件可能会更好,因为其中会有很多。我对制作无状态组件并不熟悉,并且想知道我应该在哪里定义 和 中定义的函数。Ballsthis.update()this.drawfunction Ball()

无状态组件的函数是在组件内部还是在外部?换句话说,以下哪项更好?

1:

const Ball = (props) => {
    const update = () => {
        ...
    }

    const draw = () => {
        ...
    }

    return (
       ...
    );
}

2:

function update() {
     ...
}

function draw() {
     ...
}

const Ball = (props) => {
    return (
       ...
    );
}

每种方法的优缺点是什么,其中一种对于像我这样的特定用例来说是否更好?


答案 1

首先要注意的是,无状态功能组件不能有方法,如果它是无状态功能组件,则不应指望调用或呈现。updatedrawBall

在大多数情况下,您应该在组件函数之外声明函数,以便只声明一次它们,并始终重用相同的引用。在内部声明函数时,每次呈现组件时,都会再次定义该函数。

在某些情况下,您需要在组件内部定义一个函数,例如,将其分配为事件处理程序,该事件处理程序的行为基于组件的属性而有所不同。但是,您仍然可以在外部定义函数并将其与属性绑定,从而使代码更加清晰,并使 or 函数可重用。Ballupdatedraw

// You can use update somewhere else
const update (propX, a, b) => { ... };

const Ball = props => (
  <Something onClick={update.bind(null, props.x)} />
);

如果您使用的是钩子,则可以使用来确保仅当函数的一个依赖项(在本例中)更改时才重新定义函数:useCallbackprops.x

const Ball = props => {
  const onClick = useCallback((a, b) => {
    // do something with a, b and props.x
  }, [props.x]);

  return (
    <Something onClick={onClick} />
  );
}

这是错误的方式

const Ball = props => {
  function update(a, b) {
    // props.x is visible here
  }

  return (
    <Something onClick={update} />
  );
}

当使用 时,在钩子本身中定义函数,我们的外部组件成为设计决策,而不是任何事情,你应该考虑是否要重用和/或者如果你需要访问组件的闭包范围,例如,读/写状态。就个人而言,我选择默认在组件内部定义它,并仅在需要时使其可重用,以防止从一开始就进行过度工程设计。最重要的是,重用应用程序逻辑最好使用更具体的钩子来完成,将组件留给表示目的。在使用钩子时定义组件外部的函数实际上取决于应用程序逻辑所需的与 React 的解耦等级。useCallbackupdateuseCallbackupdate

另一个常见的讨论是,是否要始终将其用于每个功能。也就是说,对待是选择加入总是可推荐的。我认为总是使用,我已经看到许多错误是由不使用函数包装引起的,而不是一个场景,当这样做以任何方式影响性能或逻辑时。在大多数情况下,您希望在依赖项不变的情况下保留引用,以便将函数本身用作其他效果、备忘录或回调的依赖项。在许多情况下,回调将作为 prop 传递给其他元素,如果您用它来记忆它,则不会更改 props(从而重新渲染)其他组件,而不管这会有多便宜或昂贵。我已经看到在组件中声明了数千个函数,并且没有一个使用会有任何缺点的情况。另一方面,大多数未被记忆的函数最终将被更改以这样做,如果开发人员不认识到不这样做的含义,则会导致严重的错误或性能问题。从技术上讲,使用 会对性能造成影响,因为您将创建附加函数,但与函数的重新声明相比,它微不足道,因为无论是否使用,以及 React 和 JavaScript 的整体占用空间。所以,如果你真的担心与不使用它相比对性能的影响,你应该问问自己 React 是否是这项工作的正确工具。useCallbackuseCallbackuseCallbackuseCallbackuseCallbackuseCallbackuseCallbackuseCallbackuseCallback


答案 2

您可以将函数放在无状态功能组件中:

function Action() {
    function handlePick(){
        alert("test");
    }

    return (
        <div>
            <input type="button" onClick={handlePick} value="What you want to do ?" />
        </div>
    )
}

但这不是一个好的做法,因为每次渲染组件时都会定义函数。handlePick()

最好在组件外部定义函数:

function handlePick(){
    alert("test");
}

function Action() {
    return (
        <div>
            <input type="button" onClick={handlePick} value="What you want to do ?" />
        </div>
    )
}