目录
  • 1.理解函数副作用
    • 什么是副作用?
    • 常见的副作用
  • 2.基础使用
    • 使用步骤
    • 示例代码
  • 3.依赖项控制

    useEffect 永远是在 DOM渲染完成之后执行

    1.理解函数副作用

    什么是副作用?

    对于React组件来说,主作用是根据数据(state/props)渲染UI,除此之外都是副作用(比如手动修改DOM、发送ajax请求)。

    常见的副作用

    • 数据请求(发送ajax)
    • 手动修改 DOM
    • localstorage操作

    useEffect 函数的作用就是为react函数组件提供副作用

    2.基础使用

    使用步骤

    • 导入 useEffect 函数
    • 调用 useEffect 函数,并传入回调函数
    • 在回调函数中编写副作用处理
    • 修改数据状态
    • 检测副作用是否生效

    示例代码

    import {useState, useEffect} from 'react';
    function App() {
    	const [count, setCount] = useState(0);
    	useEffect(() => {
    		console.log("触发副作用");
    		document.title = `点击了${count}次`;
    	});
    	return (
    		<div>
    			<button onClick={() => setCount(count + 1)}>点击{count}次</button>
    		</div>
    	)
    }

    3.依赖项控制

    副作用执行时机

    1.默认状态(无依赖项)

    上边的示例中,组件初始化时先触发一次(console出内容),之后每次点击按钮,都会触发 副作用。
    useEffect 可执行多次

    2.依赖项 为空

    useEffect 函数还可以接收第二个参数,作为该副作用的依赖项,当第二个参数 传入一个空数组[] 时,表明只有 组件初始化的时候执行一次
    咱们对上边的案例做下 微调

    function App() {
    	const [count, setCount] = useState(0);
    	useEffect(() => {
    		console.log("触发副作用");
    		document.title = `点击了${count}次`;
    	}, []); // 注意这里,传入 []
    	return (
    		<div>
    			<button onClick={() => setCount(count + 1)}>点击{count}次</button>
    		</div>
    	)
    }
    

    可以看到当点击按钮时,title 不再改变。

    3.依赖特定项

    当依赖项数组中传入值时,那么该副作用会在 组件初始化的时候执行一次,依赖的特定项变化时会再次执行

    function App() {
      const [count, setCount] = useState(0);
      const [name, setName] = useState('李白');
      useEffect(() => {
        console.log('触发渲染')
        document.title = `clicked ${count} times`;
        console.log('name: ', {name});
      },[count]) // 这里我们传入 count,不传name
      return (
        <>
          <p>当前次数:{count}</p>
          <p><button onClick={() => setCount(count + 1)}>累计</button></p>
          <p><button onClick={() => setName("杜甫")}>改名{name}</button></p>
        </>
      )
    }

    如上,当我们点击 “累计” 按钮时,会console内容,title也会改变,但是我们点击 “改名”时,不会发生变化,就是因为我们在依赖项数组中传入了 “count” 而没有 “name”。

    4.注意事项

    只要在 useEffect 回调函数中用到的数据状态就应该出现在依赖项数组中声明,否则可能会有bug。

    5.清除副作用

    在组件被销毁时,如果有些副作用操作需要被清理,比如常见的定时器等,可通过useEffect return回调函数 的方式清理副作用。

    语法如下:

    useEffect(() => {
    	console.log('副作用函数执行');
    	return () => {
    		console.log('清理副作用的函数执行');
    		// 这里执行 清理副作用的代码
    	}
    })
    

    示例:

    function Test() {
      useEffect(() => {
        let timer = setInterval(() => {
          console.log('this is effect');
        }, 1000)
        // 这里return 一个回调函数,在函数中清除副作用
        return () => {
          clearInterval(timer);
        }
      })
      return (
        <div>Test</div>
      )
    }
    function App() {
      const [flag, setFlag] = useState(true);
      return (
        <div>
          {flag ? <Test/> : null}
          <div>
            <button onClick={() => setFlag(!flag)}>点击</button>
          </div>
        </div>
      )
    }

    6.发送网络请求

    不可以直接在 useEffect 的回调函数外层直接包裹await,因为异步会导致清理函数无法立即返回
    ❌错误示例:

    useEffect(async () => {
    	const res = await getData('url');
    	console.log(res);
    })

    可在 useEffect 中定义一个请求数据方法,调用。

    正确示例

    useEffect(() => {
    	async function initData() {
    		const res = await getData('url');
    		console.log(res);
    	}
    	initData()
    }, []) // 仅组件初始化时调用
    声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。