React---hooks副作用(useEffect、useLayoutEffect)场景-区别

75 阅读3分钟

useEffect使用场景

1、数据获取:组件挂载时获取数据(空依赖数组)

  useEffect(() => {
    async function getData() {
      const res = await fetch('http://example.cn');
      const jsonRes = await res.json();
      setList(jsonRes.data.channels);
    }

    getData();
  }, []);

数据获取写法会导致首次渲染闪烁(先渲染undefined,再更新)

export const getUser = preload(() => fetch('/api/user').then(res=>res.json()))

//页面内
const data = use(getUser())

2、订阅:在组件中订阅外部数据源(如websocket链接)

useEffect(() => {
  function onMessage(event) {
    setMessage(event.data);
  }
  const socket = new WebSocket('wss://example.com/api/data');
  socket.onmessage = onMessage;
 
  // 清理订阅,防止内存泄漏
  return () => {
    socket.close();
  };
}, []); // 同样,只在组件挂载时运行一次

3、手动更改DOM:在某些情况下(使用第三方库直接操作DOM时)

useEffect(() => {
  const element = document.getElementById('some-element');
  element.style.backgroundColor = 'blue';
}, []); // 只在组件挂载时运行一次

4、清理资源:组件卸载时,可能需要执行一些清理操作,取消订阅或清除定时器

useEffect(() => {
  const intervalId = setInterval(() => {
    // 执行一些操作...
  }, 1000);
 
  return () => clearInterval(intervalId); // 清理定时器
}, []); // 只在组件挂载时运行一次,并在卸载时清理

5、依赖项变化时的副作用

6、设置定时器

什么情况下,使用useEffect无效?

1、依赖项未更新

useEffect的依赖数组中没有正确包含所有需要的依赖项,那么当这些依赖项改变时,useEffect不会重新运行。

useEffect(() =>{
  // 仅当count改变时才执行
},[count])

如果count依赖于另一个变量otherValue但没有包括在依赖数组中,那么当otherValue改变时,useEffect不会触发。

2、无限循环

在useEffect的回调函数中直接或间接地修改其依赖项,将导致无限循环的副作用调用。

useEffect(() =>{
 setCount(count + 1)//将导致useEffect再次执行
},[count])

3、错误的清理函数

如果useEffect返回一个清理函数,但在某些情况下这个清理函数没有被正确调用,可能会导致副作用没有被正确清理。确保在组件卸载时清理资源。

useEffect(() =>{
  return () => {
    //清理逻辑
  }
},[])//确保在组件卸载时清理

4、错误的依赖项数组

如果依赖项数组为空([]),那么useEffect仅在组件挂载后运行一次。如果执行逻辑需要在每次渲染后都运行,应该省略依赖项数组或包含所有必要的依赖项。

useEffect(() =>{
  //每次渲染后都执行
})

5、条件渲染问题

如果useEffect被包裹在条件语句中,可能会导致在某些条件下不执行。确保useEffect总是处于正确的组件作用域内。

if(someCondition){
  useEffect(()=>{
    // 逻辑
  },[dependency])
}

useLayoutEffect

React 的 useLayoutEffect 是一个在 DOM 更新后同步调用效果的 React Hook,它在组件的生命周期中处于 componentDidMount 和 componentDidUpdate 之间的阶段,但它会在浏览器绘制任何东西之前同步执行。

使用场景

  • DOM操作:需要在页面渲染之前操作DOM(比如滚动条位置、修改样式、元素大小调整等)
  • 测量和布局计算:测量DOM元素尺寸/位置(动态调整布局)
  • 避免闪烁:同步修改DOM样式避免闪烁

useEffect 与useLayoutEffect的区别

执行时机不同

在commit阶段不同时机执行,

  • useEffect在commit阶段结尾异步调用,
  • useLayoutEffect/componentDidMount同步调用。