问题背景
想实现点击按钮就改变数据的效果,但是在控制台的打印结果,总是上一次的修改情况,并不是最新的修改后的数据
代码:
import { useState, useRef } from "react";
// 实现sonA的数据传递给sonB
const SonA = () => {
const [sonAName, setAName] = useState("");
const sonARef = useRef(null);
const changeAName = () => {
console.log("sonARef.current.value", sonARef.current.value);
setAName(sonARef.current.value);
console.log("sonAName:", sonAName);
};
return (
<div>
<input type="text" ref={sonARef} />
<button onClick={changeAName}>changeAName</button>
</div>
);
};
const SonB = () => {
return <div>SOnB</div>;
};
const App = () => {
return (
<div>
<SonA> </SonA>
<SonB></SonB>
</div>
);
};
export default App;
原理解释:
在 React 中,useState
是一个异步更新状态的 Hook,因此在调用 setAName
更新状态后,sonAName
并不会立即改变,而是会在下一次渲染时才会更新。
因此,在 console.log("sonAName:", sonAName);
这行代码中,你看到的仍然是更新前的 sonAName
的值。
如果你想在状态更新后立即获取最新的状态值,可以考虑使用 useEffect
来监听状态的变化,然后在回调函数中执行相应的逻辑。
你可以这样修改 SonA
组件:
import React, { useState, useRef, useEffect } from "react";
const SonA = () => {
const [sonAName, setAName] = useState("");
const sonARef = useRef(null);
useEffect(() => {
console.log("sonAName:", sonAName);
}, [sonAName]);
const changeAName = () => {
console.log("sonARef.current.value", sonARef.current.value);
setAName(sonARef.current.value);
};
return (
<div>
<input type="text" ref={sonARef} />
<button onClick={changeAName}>changeAName</button>
</div>
);
};
const SonB = () => {
return <div>SOnB</div>;
};
const App = () => {
return (
<div>
<SonA />
<SonB />
</div>
);
};
export default App;
这样,在 sonAName
发生变化时,useEffect
就会被触发,你就能够在控制台中看到最新的 sonAName
值了。
页面渲染的数据正常??
虽然打印出来的数据总是显示上一次的数据,但是在页面显示的时候是实时更新的,没有延后的问题
原理解释:
这是因为 useState
的更新是异步的,setAName
不会立即改变 sonAName
的值。在 React 中,状态更新是批量处理的,所以在调用 setAName
后,React 并不会立即更新 sonAName
的值。
而在 React 中,组件重新渲染时会获取到最新的状态值,因此当 sonAName
的值在组件重新渲染时已经更新时,页面中显示的 {sonAName}
是最新的值。
而在 changeAName
函数中的 console.log("sonAName:", sonAName);
这行代码中,你看到的是更新前的 sonAName
值,因为 setAName
的更新并没有立即改变 sonAName
的值,而是在下一次渲染时才生效。
如果你想要在状态更新后立即获取最新的状态值,可以考虑使用 useEffect
来监听状态的变化,然后在回调函数中执行相应的逻辑。这样可以确保在状态更新后获取到最新的值。