当前位置: 首页 > wzjs >正文

h5网站建设 网站定制开发做网站推广有用吗

h5网站建设 网站定制开发,做网站推广有用吗,wordpress统计插件下载,南昌网站建设案例子组件使用了 React.memo ,为什么 “prop 值未发生改变”,子组件依然被重新渲染了? 🚧 示例:点击子组件中按钮,获取 input 数据进行提交(常见于表单) index.tsx import Author f…

子组件使用了 React.memo ,为什么 “prop 值未发生改变”,子组件依然被重新渲染了?
在这里插入图片描述

🚧 示例:点击子组件中按钮,获取 input 数据进行提交(常见于表单)

index.tsx

import Author from './Author.tsx';export default function Index() {const [val, setVal] = useState('');const consoleValue = () => {console.log(val);}return (<><input type="text" value={val} onChange={(e) => setVal(e.target.value)} /><Author name="李刚" onClick={consoleValue} /></>);
}

Author.tsx

export default function Author({ name, onClick }: { name: string; onClick: () => void }) {console.log('Author');return (<div><button onClick={onClick}>{name}</button></div>);
}

🐋 现象:input 每次输入值,<Author> 组件就被重新渲染一次【prop onClick 发生了变化】!

state val值变化
prop onClick变化
用户输入
触发index组件重新渲染
consoleValue重新生成
Author重新渲染

🐒 使用 memo ,在 props 没有改变的情况下跳过重新渲染!

index.tsx

const AuthorMemo = React.memo(Author);export default function Index() {const consoleValue = useCallback(() => {console.log(val);}, [val]);return (<>{/* 省略 */}<AuthorMemo name="李刚" onClick={consoleValue} /></>);
}

这里需要使用 useCallback(fn, dependencies) 来处理渲染期间传递普通函数,避免传递给组件的 props 始终不同

因为 <Author> 中要获取最新的 val 值,因此 useCallback() 中追加了 val 作为 dependencies

每次 <input> 输入,val 值都发生变化、从而导致 consoleValue 重新生成,因此 <AuthorMemo> 依然每次会重新渲染!

1️⃣ 传递依赖项数组: 初始渲染后以及依赖项变更后 运行

const consoleValue = useCallback(() => {// ...
}, [val]); // val 变更时返回一个新的函数

2️⃣ 传递空依赖项数组:仅在 初始渲染后 运行

const consoleValue = useCallback(() => {// ...
}, []); // 初始化后,不会再执行

3️⃣ 不传递依赖项数组:每次渲染之后 运行

const consoleValue = useCallback(() => {// ...
}); // 每一次都返回一个新函数:没有依赖项数组

🐇 上述问题应该如何解呢?

【有缺陷】方案一:memo 支持自定义 arePropsEqual 来确定是否重新渲染!

const MemoizedComponent = memo(SomeComponent, arePropsEqual?)
const AuthorMemo = React.memo(Author, (_prevProps, nextProps) => {/*** 可选参数 arePropsEqual:一个函数,接受两个参数:组件的前一个 props 和新的 props。* 如果旧的和新的 props 相等,即组件使用新的 props 渲染的输出和表现与旧的 props 完全相同,则它应该返回 true。否则返回 false。* 通常情况下,你不需要指定此函数。默认情况下,React 将使用 Object.is 比较每个 prop。*/return _prevProps.name === nextProps.name;
});export default function Index () {const consoleValue = useCallback(() => {console.log(val);}, [val]);
}

该方案的问题:获取的 val 值为一直为初始值,无法获取输入的最终 val 值。

🐇 问题分析:典型的 React 中的闭包问题。

React 中:组件内的每个函数都是一个闭包,因为组件本身只是一个函数。

理论上,当 val 发生变化时,consoleValue 函数会被重新创建,从而捕获最新的 val 值。然而,如果 AuthorMemo 没有重新渲染,或者 Author 组件内部没有正确处理 onClick 的更新【React.memo 比较算法导致 _prevProps.name === nextProps.name;】,可能会导致 consoleValue 没有捕获到最新的 val 值。


【推荐】方案二:ref + useEffect 组合实现。

借助 ref 每次渲染间存储信息及修改不会触发渲染的特性;

const AuthorMemo = React.memo(Author);export default function Index() {const [val, setVal] = useState('');const ref = useRef<(() => void) | undefined>();// 省略 dependencies 参数,则在每次重新渲染组件之后,将重新运行 Effect 函数useEffect(() => {// 每次更新,指向一个新的函数// .current 属性可以随时被更新,因此它不会受到闭包的限制ref.current = () => {console.log(val);};});// 依赖数组为空 [] 在整个组件的生命周期中只会被创建一次(初始化)const consoleValue = useCallback(() => {ref.current?.();}, []);return (<><input type="text" value={val} onChange={(e) => setVal(e.target.value)} /><AuthorMemo name="李刚" onClick={consoleValue} /></>);
}
  • ref 用于渲染之间 存储信息(普通对象存储的值每次渲染都会重置);
  • useEffect(() => {}) 每次渲染执行;
    • ref.current = ... 改变 ref.current 属性时,React 不会重新渲染组件;
  • const consoleValue = useCallback(() => {}, []) 只初始渲染运行、确保了 consoleValue 不发生变化(useCallback 在多次渲染中缓存函数)。
state变化&触发渲染
初始化
input 输入值
Author不重新渲染
(prop未变化)
consoleValue 因useCallback被缓存
useEffect 执行
ref.current 被赋值
Author组件渲染
useCallback 执行
useEffect 执行
ref.current 被赋值
useState(initialState) 
useRef(initialValue)

initialState:这个参数在首次渲染后被忽略。

🐇 原理分析:为什么没有闭包问题

  1. 为了让函数能够访问最新状态,每次重新渲染时都需要重新创建函数,这是无法避免的,这也是闭包的本质,与 React 无关;
  2. 利用 Ref 是一个可变对象这一特性,从而摆脱 “过期闭包” 的问题。我们可以在过期闭包之外更改 ref.current,然后在闭包之内访问它,就可以获取最新的数据。

通过 useRefuseEffect 动态更新引用的函数,避免了闭包问题。consoleValue 函数虽然在整个组件生命周期中保持不变,但它通过调用 ref.current 来间接访问最新的 val 值。

1️⃣ 传递依赖项数组: 初始渲染后以及依赖项变更的重新渲染后 运行

useEffect(() => {// ...
}, [a, b]); // 如果 a 或 b 不同则会再次运行

2️⃣ 传递空依赖项数组:仅在 初始渲染后 运行

useEffect(() => {// ...
}, []); // 不会再次运行(开发环境下除外)

3️⃣ 不传递依赖项数组:每次渲染之后 运行

useEffect(() => {// ...
}); // 总是再次运行

文章转载自:

http://X0Q71nAh.gnkbf.cn
http://aJ927S0i.gnkbf.cn
http://p81GHES2.gnkbf.cn
http://NLVQEbvF.gnkbf.cn
http://guNgOz0V.gnkbf.cn
http://xEz611IO.gnkbf.cn
http://kArjIVuX.gnkbf.cn
http://dRXeJdio.gnkbf.cn
http://y5W13pBb.gnkbf.cn
http://js5VuxUH.gnkbf.cn
http://QpIGbVey.gnkbf.cn
http://w53BfX9B.gnkbf.cn
http://yrkwCG6O.gnkbf.cn
http://0gXGXmY3.gnkbf.cn
http://fG3JGZYp.gnkbf.cn
http://9oALeTqL.gnkbf.cn
http://BpThtFoa.gnkbf.cn
http://thMRm54M.gnkbf.cn
http://WLWm00O4.gnkbf.cn
http://FjLChB8G.gnkbf.cn
http://m2Uoo9p2.gnkbf.cn
http://XiUuSCqV.gnkbf.cn
http://dXKTnqnF.gnkbf.cn
http://Hpnp4VXj.gnkbf.cn
http://mhjf6qxr.gnkbf.cn
http://DMmEkAzH.gnkbf.cn
http://JnnLWrra.gnkbf.cn
http://XKV5TEem.gnkbf.cn
http://R40pxa4V.gnkbf.cn
http://UVRD4BnE.gnkbf.cn
http://www.dtcms.com/wzjs/651165.html

相关文章:

  • 装修公司做宣传在哪个网站企业建站系统cms
  • 北京网站制作公司报价网站建设服务器软件
  • 东莞化工网站建设做外贸怎么能上国外网站
  • 重庆网站排名推广手机网站做分享到朋友圈
  • 网站手机站怎么做的WordPress影视采集
  • 微官网 手机网站我想带货怎么找货源
  • 丹东做网站的网站竞价词怎么做
  • 网站备案验证码错误温州营销网站制作报价
  • 南阳河南网站建设价格门户网站的营销特点
  • 澄海建网站软件工程师报名官网
  • 做网站海报用什么app免费网站重生九零做商女
  • 易名中国域名门户网站住房和城乡建设部网站造价师
  • 苏州网站建设 苏州网络推广专家建立网站培训讲义
  • 番禺做网站费用昆山网站开发
  • 如何成立网站软件开发平台
  • 郑州营销型网站制作运营免费建自己的网站
  • 公司企业邮箱申请中山搜索引擎优化
  • 一流专业建设规划广州网站建设公司推荐乐云seo
  • 户外旅游网站模板wordpress 正文宽度
  • 长乐区建设局网站wordpress novelist
  • 学校如何重视校园网站建设自己做网站广告法
  • 燕郊医院网站建设佛山seo代理计费
  • 北京商城型网站建设学校网站的服务器
  • 建网站不做广告怎么赚钱pathon做网站
  • 北风风淘网站开发网络营销是什么的思维导图
  • 网站域名地址seo是搜索引擎优化
  • 购物网站功能设计免费素材哪里找
  • 如何用ps做网站首页的图片怎么进行网站维护
  • 可以发布外链的网站北京网站优化企业
  • 做网站背景图怎么插网站换域名做301会有影响