我的问题与使反应挂钩成为可能的Javascript机制有关。
React的最新发展使我们能够创建钩子。对于React状态,在以下简单函数中:
function App () { const [someVar, setSomeVar] = useState('someVarDefaultValue'); return ( <div onClick={() => setSomeVar('newValue')}>{someVar} </div> ); }
挂钩useState返回带有访问器和变量的数组,我们通过App函数内部的数组分解来使用它们。
useState
因此,在幕后,该钩子看起来像(只是一个伪代码):
function useState(defaultValue) { let value = defaultValue; function setValue(val) { value = val; } return [value, setValue]; }
当您在JS中尝试此方法时,它将无法正常工作- 如果您在setValue某处使用,从数组分解的值将不会更新。即使您将value用作对象,也不能使用Primitive defaultValue。
setValue
value
defaultValue
我的问题是挂钩机制在JS中如何工作?
从我在React 源代码中看到的内容来看,它使用reducer函数和对Flow进行类型检查。对于我来说,要理解全局,代码很棘手。
这个问题不是关于如何在React中编写自定义钩子。
您必须将值存储在函数外部,以便在调用之间返回持久性结果。另外,设置该值必须在其调用的组件上重新渲染:
// useState must have a reference to the component it was called in: let context; function useState(defaultValue) { // Calling useState outside of a component won't work as it needs the context: if(!context) throw new Error("Can only be called inside render"); // Only initialize the context if it wasn't rendered yet (otherwise it would re set the value on a rerender) if(!context.value) context.value = defaultValue; // Memoize the context to be accessed in setValue let memoizedContext = context; function setValue(val) { memoizedContext.value = val; // Rerender, so that calling useState will return the new value internalRender(memoizedContext); } return [context.value, setValue]; } // A very simplified React mounting logic: function internalRender(component) { context = component; component.render(); context = null; } // A very simplified component var component = { render() { const [value, update] = useState("it"); console.log(value); setTimeout(update, 1000, "works!"); } }; internalRender(component);
然后,在setValue被调用时,组件useState将重新渲染,然后将再次被调用,并且将返回新值。