React useEffect 如何监视和更新状态? [复制]
Posted
技术标签:
【中文标题】React useEffect 如何监视和更新状态? [复制]【英文标题】:How can React useEffect watch and update state? [duplicate] 【发布时间】:2020-11-08 18:09:15 【问题描述】:示例代码
export function useShape ()
const [state, setState] = useState(
shape: 'square',
size:
width: 100,
height: 100
)
// Change shape name while size update
useEffect(()=>
const size: width, height = state
setState(
...state,
shape: width===height ? 'square' : 'rect'
)
, [state, state.size])
预期
当尺寸更新时,副作用会根据宽度,高度改变尺寸名称。
目标是使状态保持一致,因此无论大小如何变化,我都能得到正确的形状。
但有问题
useEffect函数进入循环,如果我去掉'state'依赖就好了,但是intelliSense请求了'state'依赖,那么解决办法是什么?
【问题讨论】:
每个状态值都应该用自己的 useState 钩子存储,不要将所有状态存储在同一个对象中。更不用说您根本不应该将计算值存储为状态。如果 shape 的值可以从 size 计算出来,那么就不要将 shape 存储在 state 中,只需要在需要的时候计算即可。 我试过了没有报错! 【参考方案1】:useEffect 函数进入循环...
那是因为你每次都为state
创建一个新对象,而state
被列为依赖项。
当使用钩子而不是构建多部分状态对象时,通常最好使用较小的部分。在这种情况下,我会使用三个:
const [shape, setShape] = useState("square");
const [width, setWidth] = useState(100);
const [height, setHeight] = useState(100);
useEffect(() =>
setShape(width === height ? "square" : "rect");
, [width, height]);
现在,您设置的 (shape
) 不是效果挂钩的依赖项,因此它不会无休止地触发。
const useState, useEffect = React;
function Example()
const [shape, setShape] = useState("square");
const [width, setWidth] = useState(100);
const [height, setHeight] = useState(100);
useEffect(() =>
setShape(width === height ? "square" : "rect");
, [width, height]);
function onWidthInput(target: value)
setWidth(+value);
function onHeightInput(target: value)
setHeight(+value);
return <div>
<div>
Width: <input type="number" value=width onInput=onWidthInput />
</div>
<div>
Height: <input type="number" value=height onInput=onHeightInput />
</div>
<div>
Shape: shape
</div>
</div>;
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
如果你愿意的话,你可以用你现有的状态对象来做到这一点:
useEffect(() =>
setState(current =>
const size: width, height = current;
return
...current,
shape: width === height ? "square" : "rect"
;
);
, [state.size, state.size.width, state.size.height]);
const useState, useEffect = React;
function Example()
const [state, setState] = useState(
shape: 'square',
size:
width: 100,
height: 100
);
useEffect(() =>
setState(current =>
const size: width, height = current;
return
...current,
shape: width === height ? "square" : "rect"
;
);
, [state.size, state.size.width, state.size.height]);
function onSizePropInput(target: name, value)
setState(current =>
return
...current,
size:
...current.size,
[name]: +value
;
);
const shape, size: width, height = state;
return <div>
<div>
Width: <input type="number" name="width" value=width onInput=onSizePropInput />
</div>
<div>
Height: <input type="number" name="height" value=height onInput=onSizePropInput />
</div>
<div>
Shape: shape
</div>
</div>;
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
注意其中setState
的回调形式的使用。您需要状态的 then-current 版本,而不是第一次创建效果回调时的状态,因为您用于更新的部分内容不是依赖项(因此可能是陈旧的)。
【讨论】:
【参考方案2】:您可以查看此sandbox link 以获得解决方案
无限循环是由于在 useEffect 中修改状态本身时将“状态”作为依赖项。
解决方案是通过将视图变量与受控变量分开来解耦状态。
这是定义 useShape 钩子的方法。
function useShape()
const [shape, setShape] = useState("square");
const [dimension, setDimension] = useState(
width: 100,
height: 100
);
// Change shape name while size update
useEffect(() =>
const height, width = dimension;
setShape(height === width ? "square" : "react");
, [dimension, dimension.height, dimension.width]);
return [shape, setDimension];
这样您可以公开您的 Dimension setter,并将变量视为独立的 Pieces。
【讨论】:
谢谢,这真的很有帮助。以上是关于React useEffect 如何监视和更新状态? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何使用/不使用 useEffect 钩子在 React JS 函数中获取更改的(新)状态值?
React 无法在 useEffect 内部设置状态,不会在当前周期更新状态,而是在下一个周期更新状态。这可能是啥原因造成的?
无法对未安装的组件执行 React 状态更新(useEffect 反应挂钩)
React:“无法在未安装的组件上执行 React 状态更新”,没有 useEffect 功能