React – 为什么我需要在由useState调用的函数周围包装一个匿名函数?

huangapple go评论73阅读模式
英文:

React - why do I need to wrap functions called by useState in an anonymous function?

问题

我一直在参加一门React性能培训课程,这个代码库被用作示例: https://github.com/stevekinney/wordman/blob/main/src/components/application.jsx#L10

当我们在useState()内调用函数时,它在每次重新渲染时都会被调用,即使correctAnswer的实际值没有改变。如果函数很大且复杂,这可能会导致性能问题。

例如:

const [correctAnswer, setCorrectAnswer] = useState(generateRandomColor());

为了避免这种情况,我必须将其包装在匿名函数中,或者不在useState钩子内调用该函数。

例如:

const [correctAnswer, setCorrectAnswer] = useState(() => generateRandomColor());
// 或者
const [correctAnswer, setCorrectAnswer] = useState(generateRandomColor);

为什么会这样?JavaScript背后发生了什么?

英文:

I have been taking a React performance training course and this code base is used as an example: https://github.com/stevekinney/wordman/blob/main/src/components/application.jsx#L10

When we call the function inside of useState() it is called on every re-render even though the actual value of correctAnswer does not change. If the function was large and complicated, this could cause a performance issue.

e.g.

const [correctAnswer, setCorrectAnswer] = useState(generateRandomColor());

To avoid this, I have to wrap it in an anonymous function or not invoke the function within the useState hook.

e.g.

const [correctAnswer, setCorrectAnswer] = useState(() => generateRandomColor());
const [correctAnswer, setCorrectAnswer] = useState(generateRandomColor);

Why is that? What is going on behind the scenes in JavaScript?

答案1

得分: 1

当你显式调用函数 generateRandomColor() 时,函数会在每次渲染时被调用。函数被调用是因为封装的函数组件被执行,并且你手动执行了该函数(注意括号)。

当你将函数传递给 useState 而不调用它(注意没有括号),useEffect 仅在初始化时执行它:

useState(generateRandomColor);

传递匿名函数是相同的。你传递一个函数,希望 useEffect 仅在初始化时调用它。

英文:

When you call the function explicitly generateRandomColor(), the function is called on each render. The function is called because the wrapping function component is executed, and you manually execute the function (note the parentheses).

When you pass the function to useState without calling it (note the lack of parentheses), the useEffect would only execute it when initializing:

useState(generateRandomColor);

Pass an anonymous function is identical. You pass a function that you want the useEffect to call only on init.

答案2

得分: 1

JavaScript背后发生了什么?

这与语言本身实际上没有太大关系,主要是React函数组件和useState的工作原理。每当组件需要渲染时,都会调用你的函数,但正如你所说,useState仅在第一次渲染时使用你给它的初始值;之后,它完全忽略你提供的值。但是useState(generateRandomColor())的意思是:

  • 运行generateRandomColor,获取其返回值
  • 将该返回值传递给useState

由于useState在第一次渲染后会忽略传入的值,这意味着在第一次以外的任何渲染中调用generateRandomColor都是没有意义的。

这就是为什么useState允许你传递一个函数的原因:它只会在第一次渲染时调用该函数。因此,如果该函数没有任何参数,你可以使用useState(generateRandomColor);将函数传递给useState,它将在第一次调用并在其他时间忽略它。(如果该函数需要参数,那么你将需要一个包装函数。)

英文:

> What is going on behind the scenes in JavaScript?

It's not really anything to do with the language, it's just how React function components and useState work. Your function is called every time the component needs to render, but as you said, useState only uses the initial value you give it on the first render — after that, it completely ignores what you give it. But useState(generateRandomColor()) means this:

  • Run generateRandomColor, get its return value
  • Pass that return value into useState

Since useState will ignore the passed value after the first render, that means the call to generateRandomColor is pointless on any render but the first.

That's why useState allows you to pass in a function instead: It will only call the function on the first render. So if the function doesn't have any parameters, you can do useState(generateRandomColor); to pass the function to useState, which will call it the first time and ignore it other times. (If the function needed parameters, then you'd need a wrapper function.)

huangapple
  • 本文由 发表于 2023年3月15日 20:24:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75744656.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定