原因

合并更新造成的数据不能及时更新(非标准异步过程)
为什么我会在我的函数中看到陈旧的 props 和 state ?

解决方案

1.使用useRef存值

在useEffect中监听state变化,存进ref中

import './App.css';
import React, { useState,useRef,useEffect} from 'react';

function App() {
    let [count,setCount]=useState(0)
    const myRef = useRef(null);
    const handleClick=(d)=>{
       setCount(count+3)
       console.log(myRef.current)
    }
    useEffect(() => {
        myRef.current=count+3
   }, [count])
  return (
    <div className="App">
      <header className="App-header">
            <p>{count}</p>
            <button onClick={handleClick}>+</button>
      </header>
    </div>
  );
}

export default App;

2.直接用useEffect监听变量
import './App.css';
import React, { useState,useRef,useEffect} from 'react';

function App() {
    let [count,setCount]=useState(0)
    const handleClick=(d)=>{
       setCount(count+3)
    }
    useEffect(() => {
       console.log(count)
   }, [count])
  return (
    <div className="App">
      <header className="App-header">
            <p>{count}</p>
            <button onClick={handleClick}>+</button>
      </header>
    </div>
  );
}

export default App;


3.回调函数传参

函数式更新
如果新的 state 需要通过使用先前的 state 计算得出,那么可以将函数传递给setState。该函数将接收先前的 state,并返回一个更新后的值。


function Example2() {
  const [number, setNumber] = useState(0);

  const lazy1 = () => {
    // 获取点击按钮时的 state
    setNumber(number + 1);
  };

  const lazy2 = () => {
    // 每次执行时都会再去获取新的 state,而不是使用点击触发时的 state
    setNumber(number => number + 1);
  };

  return (
    <div>
      <p>{number}</p>
      <button onClick={() => setNumber(number + 1)}>+</button>
      <br />
      <button onClick={lazy1}>lazy1:只能获取点击按钮时候的状态</button>
      <br />
      <button onClick={lazy2}>lazy2:每次执行都会重新获取state, 所以获取的都是最新的state</button>
    </div>
  );
}

export default Example2;

4.自定义hooks

export function useCallbackState(state) {
  const cbRef = useRef();
  const [data, setData] = useState(state);

  useEffect(() => {
    cbRef.current && cbRef.current(data);
  }, [data]);

  return [
    data,
    function(val, callback) {
      cbRef.current = callback;
      setData(val);
    },
  ];
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐