场景
在react中,有的时候我们会在useEffect中去执行set操作,如下
function A() {
console.log("A render")
const [,update] = useState()
useEffect(() => {
update()
}, [])
return <B/>
}
function B() {
console.log("B render")
}
由于useEffect内的函数是异步调用的,在第一次渲染完成后开始第二次渲染,以上代码输出
A render
B render
A render
B render
可以看到子组件渲染了两次,其实是没有必要的,我们可以封装一个同步调用的useEffect
function useSyncEffect(fn, deps) {
const dp = useRef([])
function run() {
dp.current = deps
fn()
}
if (dp.current.length !== deps.length) {
run()
} else {
for (let i = 0; i < deps.length; i++) {
if (deps[i] !== dp.current[i]) {
run()
break
}
}
}
}
将以上代码改为
function A() {
console.log("A render")
const [,update] = useState()
useSyncEffect(() => {
update()
}, [])
return <B/>
}
function B() {
console.log("B render")
}
输出结果
A render
A render
B render
缺陷
因为这个方法是同步调用的,用useRef所以绑定dom的话,ref.current是undefined,这个时候还是应该用useEffect
function A() {
console.log("A render")
const ref = useRef()
useSyncEffect(() => {
console.log(ref.current)//undefined
}, [])
return <div ref={ref}></div>
}