英文:
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.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论