良匠网站建设,网站重要三要素,如何维护公司网页,成都设计公司注册文章目录 一、useCallback二、forwardRef 总结了useCallback、forwardRef中的deps#xff0c;以及操作子组建时会遇到数据流不同步的问题 一、useCallback useCallback可以缓存函数#xff0c;这样避免组建更新导致的函数重建#xff1b;useCallback在函数更新以后会在deps中… 文章目录 一、useCallback二、forwardRef 总结了useCallback、forwardRef中的deps以及操作子组建时会遇到数据流不同步的问题 一、useCallback useCallback可以缓存函数这样避免组建更新导致的函数重建useCallback在函数更新以后会在deps中对比每一项有值的变化会更新函数中依赖项的最新值重新创建函数如果没有触发deps那么这个函数不会重新创建并且函数内使用的state值也不会变化尤其是累加赋值但是useRef变量永远是最新值一般不需要去依赖useRef值除非他的值变化了需要去刷新函数没有deps如果只是使用setState消息队列如setCount((count) count 1)则可以拿到最值但是也只是在函数内部使用set函数外部依旧不会拿到最新值函数也拥有地址会被deps捕获识别useCallback可以缓存函数即函数地址不会更改 import { Col, message, Row, Space } from antd;
import { forwardRef, useCallback, useImperativeHandle, useRef, useState } from react;export default function ParentRef() {const countRef useRef(0);const [count, setCount] useState(0);const [name, setName] useState(0);// 每一次组建更新都会生成新的函数addFunc在其他hooks都deps中都会被识别成值产生变化const addFunc () {setCount(count 1);countRef.current countRef.current 1;};// useCallback 中的 deps 变化才会触发重新生成新的函数// 没有触发deps更新也可以调用但是其中的依赖项使用之前的快照值set队列函数会显示正常const handleClick useCallback(() {setCount(count 1); // 引发组件更新countRef.current countRef.current 1; // 不会引发组件更新值的对比// deps 数值或者引用地址的变化都会触发重新调用生成新的handle}, [countRef.current]);return (divpParent/pbutton onClick{handleClick}Focus Input/buttonhr //div);
}
二、forwardRef forwardRef控制子组建useImperativeHandle暴露子组建属性在页面代码拆分以后组件逻辑分布分散使用forwardRef可以快速操作子组建完成动作而避开了传参的麻烦useImperativeHandle也有deps依赖类似于useCallback的deps只有deps依赖变化才会重新创建createHandle并更新函数内部的依赖项父组件修改state类似异步并且调用子组建init类似同步这个时候是来不及更新init中的依赖的调用时使用了旧值所以同步调用子组建init会拿到实时值但是很有可能你希望获取最新值一种解决方式是在init参数传入最新值一种解决方式是子组建监听值的变化调用对应的函数控制子组建init会避开数据流导致在数据流变化之前就触发函数需要注意init函数和最新的数据流的关系注意子组建中 await delay(0)然后setCount(count 1)点击两次发现打印001122… 第一次点击打印函数体内count 0, delay(0) (deps变化) 更新函数体内count 0此时setCount还没有值更新count 1实际值count 第二次点击打印函数体内count 0delay(0) (deps变化) 更新函数体内count 1实际值countcount 1实际值count 第三次点击才会打印count为1 import { Col, message, Row, Space } from antd;
import { forwardRef, useCallback, useImperativeHandle, useRef, useState } from react;
const delay (ms) new Promise((resolve) setTimeout(resolve, ms));
export function ChildRefTemp(props, ref) {const inputRef useRef(null);const [count, setCount] useState(0);const [age, setAge] useState(0);const handleClick () {inputRef.current.focus();};const countAdd async () {// await delay(0);// 当设置延迟props.count先让createHandle更新这个时候count还没有更新还是旧值展示// 除了第一次点击其他时候点击两次才可以让count 1setCount(count 1);};// useImperativeHandle: (ref, createHandle, deps)useImperativeHandle(ref,() {console.log(ChildRefTemp useImperativeHandle); // 初始化也会调用一次return {init(initCount) {inputRef.current.focus();countAdd();message.success(init count);message.success(init props.countRef: props.countRef);message.success(init initCount: initCount);}};},// 这里的deps依赖会导致重新调用 createHandle如果没有依赖获取值的时候得不到最新值// [age] 不会导致重新调用 createHandle 生成新的handle// 父组件只设置props.countRef不去setCount不会导致子组建接收到最新的props.countRef// 父组件setCount子组件接收到最新的props.count导致子组件并没有重新渲染只要这里的值判断改变createHandle 中就可以重新最新的数据[props.countRef]);return (divinput typetext ref{inputRef} /button onClick{handleClick}Focus Input/buttonRow style{{ marginTop: 10 }}ColSpacespan style{{ color: red }}ParentRefcount: {props.count}/spanspan style{{ color: red }}ParentRef countRef: {props.countRef}/spanspancount: {count}/span/Space/Col/Row/div);
}
// forwardRef: (component, props) ref component(props, ref)
const ChildRef forwardRef(ChildRefTemp);export default function ParentRef() {const childRef useRef(null);const countRef useRef(0);const [count, setCount] useState(0);const [name, setName] useState(0);// 每一次组建更新都会生成新的函数addFunc在其他hooks都deps中都会被识别成值产生变化const addFunc () {setCount(count 1);countRef.current countRef.current 1;childRef.current.init();};// useCallback 中的 deps 变化才会触发重新生成新的函数// 没有触发deps更新也可以调用但是其中的依赖项使用之前的快照值set队列函数会显示正常const handleClick useCallback(() {setCount(count 1); // 引发组件更新// setCount((count) count 1); // 消息队列countRef.current countRef.current 1; // 不会引发组件更新值的对比childRef.current.init(countRef.current);// message.success(handleClick count);// deps 数值或者引用地址的变化都会触发重新调用生成新的handle}, [countRef.current]);return (divpParent/pbutton onClick{handleClick}Focus Input/buttonhr /pChildRef/p// handleClick 函数也拥有地址会被deps捕获识别useCallback可以缓存函数即函数地址不会更改ChildRef ref{childRef} count{count} countRef{countRef.current} name{name} handleClick{handleClick} //div);
}