Javascript 如何在React函数组件中为setState创建指定的回调函数

Javascript 如何在React函数组件中为setState创建指定的回调函数,javascript,reactjs,Javascript,Reactjs,这个问题可能与其他问题相似,但事实并非如此。我面临的问题有点棘手 在官方React文档中,它说useffect可以作为setState中内联callBack函数的替代。要创建这样一个回调事件,我们需要在useffect函数上传递一个数组,并且只有在数组值发生任何变化时,useffect函数才会运行,从而创建一个回调函数 但是,假设在我的react函数组件中,我创建了一个状态,其中包含一个具有多个属性的对象 还有两个按钮,按钮1,按钮2。单击按钮1时,会触发设置状态功能,如下所示: 并调用回调函数

这个问题可能与其他问题相似,但事实并非如此。我面临的问题有点棘手

在官方React文档中,它说
useffect
可以作为
setState
中内联
callBack
函数的替代。要创建这样一个
回调
事件,我们需要在
useffect
函数上传递一个
数组
,并且只有在数组值发生任何变化时,
useffect
函数才会运行
,从而创建一个
回调
函数

但是,假设在我的react函数组件中,我创建了一个
状态
,其中包含一个具有多个属性的
对象

还有两个按钮,
按钮1
按钮2
。单击
按钮1
时,会触发
设置状态
功能,如下所示:

并调用
回调
函数,即:

当点击
按钮2
时,它也会触发
setState
。像这样:

setState({…state,姓名:“harry”,年龄:19})

与前一次一样,这次还发生了一个
回调
函数,即:

这就是一切都变得一团糟的地方。单击
按钮1
时,我希望 一个
console.log
,上面写着
“姓名、姓氏、年龄和父母姓名已更改”
,但我们得到的是:

表示单击
按钮1
时触发了
useffect
回调函数。
这不是我想要的。这同样适用于
按钮2
。之所以发生这种情况,是因为
useffect
都有一个common数组值

如果它是一个基于React类的组件,我们将在
setState
之后传递一个内联函数。但是在反应功能组件中,它变得复杂。这是现场演示


当我尝试将基于react类的组件转换为功能组件时,经常会出现这种情况。那么,我如何在React函数组件中创建一个特定的
回调
函数,该函数仅在特定的
设置状态
发生后运行?

调用这两个
useffect
是正确的。如果任何属性依赖于更改,则会触发
useffect

在您的示例中,由于两个
useffect
s都在侦听
state.name
,因此如果此值更改,这两个都将触发

对于这种方法,您要问的是如何比较当前状态和新状态
useRef
是一个很好的用例

由于您的所有状态都在一个对象中,因此您可以在一个
useffect
hook中运行所有这些,并使用
state
对象触发它:

const previousState=useRef(状态);
useffect(()=>{
if(previousState.current.name!==state.name){
控制台日志(“名称更改”);
}
如果(previousState.current.age!==状态.age){
控制台日志(“年龄更改”);
}
previousState.current={…state};//更新以前的状态
},[州];

我设计了比较,结果可能会变得一团糟。但您可以看到如何检查状态的哪些部分已更改,然后在此基础上运行条件行为。

我认为问题正是您所期望的:

这就是一切都变得一团糟的地方。单击按钮1时,我 希望得到一个console.log,上面写着“姓名、姓氏、年龄和父母姓名已更改”,但我们得到的是:

“姓名、姓氏、年龄和父母姓名已更改”
“姓名和年龄已更改”

当然,这两种效果都会被触发,因为两种效果中都有
state.name
作为deppendecy-您可以通过单击每个按钮来更改此键

尝试添加新按钮:

<button onClick={() => setState({ ...state, parent: state.parent === "live" ? "dead" : "live"})}>
        toggle parent
</button>
setState({…state,parent:state.parent==“live”?“dead”:“live”})}>
切换父项
并且将看到唯一触发了独立性的
state.parent
的效果


这是否回答了您的问题?

根据您的目标,这里有两种可能的解决方案

当您在依赖项数组中订阅的任何值发生更改时,将触发
useffect
挂钩。因此,如果我们想知道哪个值被更改了,我们可以为每个状态值添加一个单独的
useffect
hook

useEffect(() => console.log('Name changed.'), [state.name])
useEffect(() => console.log('Last Name changed.'), [state.lastName])
useEffect(() => console.log('Age changed.'), [state.age])
useEffect(() => console.log('Parent changed.'), [state.parent])
钩子很好,但不是你描述的唯一方法,事实上也不总是最好的方法。有时,您可能希望专门在按下按钮时运行代码,如:

const onButton1Pressed = () => {
  setState(prevState => ({
    ...prevState,
    name: "steve",
    lastName: "potter",
    parent: "dead"
  }))
  console.log('Changed name, lastname, parent')
}
const onButton2Pressed = () => {
  setState(prevState => ({
    ...prevState,
    name: "harry",
    age: 19
  }))
  console.log('Changed name, age')
}
useEffect(() => {
console.log("Name and age are changed")
}, [state.name, state.age])
"Name, last Name, age and parent name Changed"  
"Name and age are changed"
<button onClick={() => setState({ ...state, parent: state.parent === "live" ? "dead" : "live"})}>
        toggle parent
</button>
useEffect(() => console.log('Name changed.'), [state.name])
useEffect(() => console.log('Last Name changed.'), [state.lastName])
useEffect(() => console.log('Age changed.'), [state.age])
useEffect(() => console.log('Parent changed.'), [state.parent])
const onButton1Pressed = () => {
  setState(prevState => ({
    ...prevState,
    name: "steve",
    lastName: "potter",
    parent: "dead"
  }))
  console.log('Changed name, lastname, parent')
}
const onButton2Pressed = () => {
  setState(prevState => ({
    ...prevState,
    name: "harry",
    age: 19
  }))
  console.log('Changed name, age')
}