引言
我发现很多前端工程师们在处理一些计算合并、事件流转的过程中,喜欢用 useEffect
来处理各类问题。
例如:
import { useRequest } from 'ahooks'; import React, { useEffect, useState } from 'react'; export function comp1({ setParams }) { return <div onClick={() => setParams({ a: 1 })}>comp1</div>; } export function comp2({ defaultParams }) { const { run } = useRequest(async () => {}); // 利用 defaultParams 的变化,运行某个事件 useEffect(() => run(), [defaultParams]); return <div>comp2</div>; } export function Page() { const [defaultParams, setDefaultParams] = useState({}); return ( <> <comp1 setParams={setDefaultParams} /> <comp2 defaultParams={defaultParams} /> </> ); }
import React, { useEffect, useState } from 'react'; export function Page({ defaultParams }) { const [params, setParams] = useState(defaultParams); useEffect(() => { setParams({ ...defaultParams, appid: 'appid' }); }, [defaultParams]); return <>{JSON.stringify(params)}</>; }
上面两个例子算是比较典型的例子,都是想要说:当 xxx 变化,然后执行 xxx。
这都是典型的错误使用了 useEffect
,因为对于useEffect
和 setState
的操作,对于 React 来说并不是同步执行的,React 对于 useEffect
的解释非常清楚,useEffect:
useEffect
、useState
这类方法都是有延时的执行,因为对于 React 来说,状态的变更可能还需要处理 VDom 的生成,Diff算法,状态合并等等。这些都需要借助异步的执行才更为高效。useEffect
更是需要等待渲染结束后才会执行。
虽然这可能只是几毫秒的事情,但是如果依赖这些来做事件传递,流程处理,就意味着会出现许多中间态,因为他们不是线性同步在运行。
如果给一句话就是,请不要依赖 React 的状态变化及渲染,来干扰数据变化
最后给下上述2个例子的正确解法:
跨组件事件通信
import { useEventEmitter, useRequest } from 'ahooks'; import React from 'react'; export function comp1({ event$ }) { return <div onClick={() => event$.emit()}>comp1</div>; } export function comp2({ event$ }) { const { run } = useRequest(async () => {}); event$.useSubscription(() => run()); return <div>comp2</div>; } export function Page() { // 可以采用 Context 进行跨组件层级传递 const event$ = useEventEmitter(); return ( <> <comp1 event$={event$} /> <comp2 event$={event$} /> </> ); }
计算属性
import { useCreation } from 'ahooks'; import React from 'react'; export function Page({ defaultParams }) { const params = useCreation(() => ({ ...defaultParams, append: 'append' }), [defaultParams]); return <>{JSON.stringify(params)}</>; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)