React钩子引入了useState来设置组件状态。但是我如何使用钩子来替换下面的回调代码:
setState(
{ name: "Michael" },
() => console.log(this.state)
);
我想在状态更新后做一些事情。
我知道我可以使用useEffect来做额外的事情,但我必须检查之前的状态值,这需要位代码。我正在寻找一个简单的解决方案,可以使用useState挂钩。
React钩子引入了useState来设置组件状态。但是我如何使用钩子来替换下面的回调代码:
setState(
{ name: "Michael" },
() => console.log(this.state)
);
我想在状态更新后做一些事情。
我知道我可以使用useEffect来做额外的事情,但我必须检查之前的状态值,这需要位代码。我正在寻找一个简单的解决方案,可以使用useState挂钩。
当前回答
我不认为用useRef区分挂载与否是一个好方法,不是一个更好的方法来确定useState()在useEffect()中生成的值是否为初始值?
const [val, setVal] = useState(null)
useEffect(() => {
if (val === null) return
console.log('not mounted, val updated', val)
}, [val])
其他回答
你的问题很有道理。让我告诉您,useEffect在默认情况下运行一次,并在每次依赖数组更改之后运行一次。
请看下面的例子:
import React,{ useEffect, useState } from "react";
const App = () => {
const [age, setAge] = useState(0);
const [ageFlag, setAgeFlag] = useState(false);
const updateAge = ()=>{
setAgeFlag(false);
setAge(age+1);
setAgeFlag(true);
};
useEffect(() => {
if(!ageFlag){
console.log('effect called without change - by default');
}
else{
console.log('effect called with change ');
}
}, [ageFlag,age]);
return (
<form>
<h2>hooks demo effect.....</h2>
{age}
<button onClick={updateAge}>Text</button>
</form>
);
}
export default App;
如果你想要setState回调与钩子一起执行,那么使用标志变量并在useEffect中给出If ELSE OR If块,以便当条件满足时,只执行该代码块。无论如何,当依赖项数组改变时,效果会运行,但效果中的IF代码只会在特定的条件下执行。
如果你想要更新之前的状态,那么你可以在hooks中这样做:
const [count, setCount] = useState(0);
setCount(previousCount => previousCount + 1);
我不认为用useRef区分挂载与否是一个好方法,不是一个更好的方法来确定useState()在useEffect()中生成的值是否为初始值?
const [val, setVal] = useState(null)
useEffect(() => {
if (val === null) return
console.log('not mounted, val updated', val)
}, [val])
您需要使用useEffect钩子来实现这一点。
const [counter, setCounter] = useState(0);
const doSomething = () => {
setCounter(123);
}
useEffect(() => {
console.log('Do something after counter has changed', counter);
}, [counter]);
如果你想在第一次初始渲染时忽略useEffect回调,那么相应地修改代码:
import React, { useEffect, useRef } from 'react';
const [counter, setCounter] = useState(0);
const didMount = useRef(false);
const doSomething = () => {
setCounter(123);
}
useEffect(() => {
// Return early, if this is the first render:
if ( !didMount.current ) {
return didMount.current = true;
}
// Paste code to be executed on subsequent renders:
console.log('Do something after counter has changed', counter);
}, [counter]);
我写了自定义挂钩与typescript,如果有人还需要它。
import React, { useEffect, useRef, useState } from "react";
export const useStateWithCallback = <T>(initialState: T): [state: T, setState: (updatedState: React.SetStateAction<T>, callback?: (updatedState: T) => void) => void] => {
const [state, setState] = useState<T>(initialState);
const callbackRef = useRef<(updated: T) => void>();
const handleSetState = (updatedState: React.SetStateAction<T>, callback?: (updatedState: T) => void) => {
callbackRef.current = callback;
setState(updatedState);
};
useEffect(() => {
if (typeof callbackRef.current === "function") {
callbackRef.current(state);
callbackRef.current = undefined;
}
}, [state]);
return [state, handleSetState];
}