React钩子引入了useState来设置组件状态。但是我如何使用钩子来替换下面的回调代码:

setState(
  { name: "Michael" },
  () => console.log(this.state)
);

我想在状态更新后做一些事情。

我知道我可以使用useEffect来做额外的事情,但我必须检查之前的状态值,这需要位代码。我正在寻找一个简单的解决方案,可以使用useState挂钩。


当前回答

这个怎么样:

const [Name, setName] = useState("");
...
onClick={()=>{
setName("Michael")
setName(prevName=>{...}) //prevName is Michael?
}}

其他回答

这个怎么样:

const [Name, setName] = useState("");
...
onClick={()=>{
setName("Michael")
setName(prevName=>{...}) //prevName is Michael?
}}

我有一个非常具体的用例,我需要在dom中呈现一个类,然后设置另一个类。这就是我的解决方案,我发现它相当优雅。

const [value1, setValue1] = useState({value: 'whatever', onValue: false})


useEffect(() => {
    setValue1(prev => ({
      value: 'whatever',
      onValue: !prev.onValue, 
    }));
}, ['whatever'])

 
useEffect(() => {

// if you want to ensure the render happens before doThing2() then put it in a timeout of 1ms,
  setTimeout(doThing2, 1); 

// or if you are happy to call it immediately after setting value don't include the timeout
 doThing2()


}, [value1.onValue])

我写了自定义挂钩与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];
}

您需要使用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]);

如果你想要更新之前的状态,那么你可以在hooks中这样做:

const [count, setCount] = useState(0);


setCount(previousCount => previousCount + 1);