React自定义useLocalStorage Hook数据反向传递机制疑问
嘿,你的理解其实已经对了一半,而且你的代码本身是能正常工作的,只是没搞清楚App里更新的值怎么同步回Hook的逻辑,我来给你拆解清楚:
首先肯定你对正向传递的理解:你说的从Hook把初始值传到App的逻辑完全正确——通过useState调用getSavedValue拿到本地存储的值,再把value和setValue返回给App,App用name接收value,这部分没毛病。
接下来重点讲你困惑的反向传递:
1. setName就是Hook里的setValue,它直接操控Hook内部的状态
当你在App里写const [name, setName] = useLocalStorage("NAME", "");时,setName其实就是Hook里useState返回的setValue函数。React的useState返回的更新函数是一个闭包,它能直接访问并修改Hook内部的value状态变量。
所以当你在输入框触发onChange={(e) => setName(e.target.value)}时,本质上是在调用Hook里的setValue,直接把输入的新值更新到了Hook内部的value里。
2. Hook里的value和App里的name是“同一份状态”
Hook内部的value是响应式的状态变量,它和App组件的渲染周期绑定在一起。当setValue(也就是setName)更新了value后,App组件会重新渲染,此时Hook里的value已经是最新值,而App里的name就是这个最新值的引用——两者完全同步,根本不需要“手动传递”。
如果你想验证这一点,可以在Hook里加个打印:
function useLocalStorage(key, initialValue) { // ... 其他代码 useEffect(() => { console.log("Hook里的最新value:", value); // 每次输入都会打印最新值 localStorage.setItem(key, JSON.stringify(value)); }, [value, key]); // 这里建议加上依赖数组,优化性能 // ... 其他代码 }
当你在输入框输入内容时,控制台就会看到Hook里的value和App里的name完全一致。
3. 你的useEffect已经在做同步本地存储的工作了
你Hook里的useEffect现在会在每次组件渲染时执行(包括value更新的时候),所以每次value被setName更新后,useEffect都会把最新的value存到localStorage里——这就是你的代码能正常保存输入内容的原因。
不过这里有个小优化:现在的useEffect没有依赖数组,会导致**每次组件渲染(哪怕和value无关的渲染)**都执行存localStorage的操作,建议加上依赖数组[value, key],这样只有当value或者key变化时才执行,更高效:
useEffect(() => { localStorage.setItem(key, JSON.stringify(value)); }, [value, key]);
最后回到你的问题:你不需要“传递”App里的name到Hook里,因为name本身就是Hook里value的引用,你在Hook里直接用value就能拿到和App里name完全一致的最新值啦!
备注:内容来源于stack exchange,提问作者Dalibor Pavlik

