如何在功能组件渲染过程中正确地产生副作用



我在这里读到副作用应该属于useEffect,但由于钩子规则,这立即阻止了我在useEffect内部调用钩子。

副作用进入了不同的地方(类中的生命周期方法,或在功能组件中使用效果(

然而,在我看来,Child触发其Parent上的函数是很常见的,例如,来自子级ButtononClick。另一方面,onClick可能会产生副作用,比如更改Parent的状态,这可能会对父级和子级的渲染产生副作用。

"天真地"调用这些方法只会给我一个错误"在渲染不同的组件(Child(时无法更新组件(Parent(",尽管我在这里的目标不是解决这个错误,而是了解如何在渲染过程中应用副作用。

以下是渲染过程中的副作用示例。我无法重现那个错误,所以我不确定这种方法是否正确,是吗?

import React, { useState } from 'react';
type ButtonProps = {
color: string;
onClick: (newCounterValue: number) => void;
};
function Button({ color, onClick }: ButtonProps) {
const [counter, setCounter] = useState(0);
return (
<span style={{ backgroundColor: color }} onClick={() => {
setCounter(counter + 1);
onClick(counter + 1);
}}
>
Increase counter </span>
);
}
function App() {
const [shouldShowGreen, setShouldShowGreen] = useState(true);
const [counter, setCounter] = useState(0);
return (
<div>
<span>Counter value: {counter}</span>
<Button color={shouldShowGreen ? `green` : `blue`}
onClick={(newCounterValue: number) => {
setShouldShowGreen(newCounterValue % 2 === 0);
setCounter(newCounterValue);
}}
/>
</div>
);
}

问题中的示例代码在渲染中不会产生副作用

AppButton这两个组件都调用useState,然后返回一个值。这两种都不会产生我们需要担心的副作用。

呈现的值确实包含执行副作用的事件处理程序,但在呈现过程中并没有实际调用它们。例如,此函数只会在单击按钮时调用,而不会在渲染过程中调用:

() => {
setCounter(counter + 1);
onClick(counter + 1);
}

但是,如果您将该函数分配给了一个变量,然后在返回组件主体之前调用了它,那么会给您带来麻烦。例如,这个组件将导致您看到的错误:

function Button({ color, onClick }: ButtonProps) {
const [counter, setCounter] = useState(0);
const handleClick = () => {
setCounter(counter + 1);
onClick(counter + 1);
}
handleClick(); // Don't do this!
return (
<span style={{ backgroundColor: color }} onClick={handleClick}
>
Increase counter </span>
);
}