它们是使用包含更新的道具和先前状态的 useState 钩子来更新状态的功能形式吗?
Posted
技术标签:
【中文标题】它们是使用包含更新的道具和先前状态的 useState 钩子来更新状态的功能形式吗?【英文标题】:Is their a functional form of updating state using useState hook that contains updated props along with previous state? 【发布时间】:2022-01-02 00:18:40 【问题描述】:在基于类的 React 组件中,我们可以使用 setState 的函数形式定义处理函数,例如:
const handleClick =()=> this.setState((prevState,updatedProps)=>(// return some object ))
其中,两个参数表示传递给该组件的先前状态和更新的道具。
类似地,我们有一个函数式表单来使用 useState 钩子在函数式组件中设置状态,如下所示:
const [count, setCount] = useState(0);
const handleClick =()=> setCount(c=>c+1)
但正如我们所见,useState 钩子中的这种函数形式缺少表示更新的道具的第二个参数
这是 React 开发团队故意留下的吗? 在 useState 钩子中设置状态时,我们如何访问更新的道具以及先前的状态? 描述问题的实际代码:code sandbox link
只需在 App 组件中一次导入一个,就可以在两个 Counter 组件之间切换(一个是功能性的,另一个是基于类的)。
【问题讨论】:
使用useRef
制作自定义钩子:reactjs.org/docs/…
@morganney - 嘿!我正在寻找来自父组件的最新道具。尽管使用 useRef 也可以拥有最新的 props,但我想问为什么 React 团队使用 hook 将其从 set State 的功能签名中删除?
所以将它们存储在ref.current
中。您需要的解决方案显示在文档中。至于为什么 React 团队没有包含 usePrevious
钩子,我无法告诉你,但他们确实提供了 useRef
,所以我就使用它。
@morganney - 我不是在寻找 usePrevious 钩子,因为它给了我以前的 prop 或 state 值。而是寻找最新的道具,因为 setState 是异步的。要使用最新的道具,我仍然可以使用 ref: ref.current = props;作为功能组件内部的第一行(而不是在 useEffect 内部,因为在 useEffect 内部它将引用以前的道具)。
如果你正在寻找最新的道具,那你为什么不直接使用props
???
【参考方案1】:
你为什么不像这样触发 useEffect 中的计数(我像这样修改了你的 FunctionalCounter),在代码中读取 cmets。
(很老套的方式,所以只有当prop值被点击触发时才会改变)
import React, useState, useEffect from "react";
export default function FunctionalCounter(props)
const [count, setCount] = useState(100);
const [shouldTrigger, setShouldTrigger] = useState(false);
useEffect(() =>
if (shouldTrigger)
setCount((c) => c + props.fromParent);
setShouldTrigger(false);
, [props.fromParent,shouldTrigger]);
return (
<div>
<h3> The counter value is count</h3>
<button
onClick=() =>
props.handleUpdate();
setShouldTrigger(true);
>
Click me
</button>
</div>
);
我能想到的其他方法是返回 props.handleUpdate();
上的值,这样您就可以在不依赖父级的情况下使用它:
App.js
const handleUpdate = () =>
const newVal = appVar + 1
setAppVar(newVal);
return newVal;
FunctionalCounter.js
import React, useState from "react";
export default function FunctionalCounter(props)
const [count, setCount] = useState(100);
return (
<div>
<h3> The counter value is count</h3>
<button
onClick=() =>
const newCount = props.handleUpdate();
setCount(newCount);
>
Click me
</button>
</div>
);
【讨论】:
这行得通。即使我已经尝试过,但这个解决方案的问题是,无论我是否点击子组件上的按钮,只要父道具发生变化,这都会设置计数。我只想在单击按钮时这样做。 @gamebecks 我编辑了答案并提供了一个额外的替代解决方案。 您编辑的响应中的两个解决方案都满足要求。但是首先有一个警告,因为它会导致一次额外的重新渲染,因为 useEffect 中的 setCount 仅针对 Class 组件案例中的一个。第二个似乎合适。这让我回到了我最初的问题,为什么 React 团队没有为 useState 钩子提供更新的 props 作为类似于基于类的 setState 的第二个参数? @gamebecks 不确定,而且在我 6 年的反应经验中,我从未真正遇到过像您这样的问题。在这个特定的问题中也能意识到这一点。以上是关于它们是使用包含更新的道具和先前状态的 useState 钩子来更新状态的功能形式吗?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Relay QueryRenderer 道具更新状态