React的基本知识:useEffect

发布于:2024-11-29 ⋅ 阅读:(25) ⋅ 点赞:(0)

1. useEffect dependencies array

当组件重新渲染时,React 会检查 useEffect 中的依赖数组。如果数组中的任何值发生变化,React 会重新执行副作用函数。如果依赖项没有变化,React 会跳过副作用函数的执行。


import React from "react"


export default function App(){
  
  const [starWarsData, setStarWarsData] = React.useState({})
  const [count, setCount] = React.useState(0)

  console.log("Component rendered")

  React.useEffect(() => {
    console.log("Effect function run")
  }, [count])

  return (
    <div>
      <pre>{JSON.stringify(starWarsData, null, 2)}</pre>
      <h2>The count is {count}</h2>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>Add</button>
    </div>
    
  )
}

2. When does React run your useEffect function? When does it NOT run the effect function?

  • As soon as the component loads (first render)
  • On every re-render of the component (assuming no dependencies array)
  • Will NOT run the effect when the values of the dependencies in the array stay the same between renders

3. useEffect for fetching data


import React from "react"


export default function App(){
  
  const [starWarsData, setStarWarsData] = React.useState({})
  const [count, setCount] = React.useState(0)


  React.useEffect(function() {
    console.log("Effect ran")
    fetch("https://swapi.dev/api/people/1")
      .then(res => res.json())
      .then(data => setStarWarsData(data))
  }, [])

  return (
    <div>
      <pre>{JSON.stringify(starWarsData, null, 2)}</pre>
      <h2>The count is {count}</h2>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>Add</button>
    </div>
    
  )
}

4. useEffect: when to use dependencies


import React from "react"


export default function App(){
  
  const [starWarsData, setStarWarsData] = React.useState({})
  const [count, setCount] = React.useState(1)


  React.useEffect(function() {
    console.log("Effect ran")
    fetch(`https://swapi.dev/api/people/${count}`)
      .then(res => res.json())
      .then(data => setStarWarsData(data))
  }, [count])

  return (
    <div>
      <pre>{JSON.stringify(starWarsData, null, 2)}</pre>
      <h2>The count is {count}</h2>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>Add</button>
    </div>
    
  )
}

5. useEffect cleanup function

在 React 中,useEffect 钩子允许你执行副作用操作,并且可以返回一个清理函数(cleanup function),这个清理函数会在几个关键的时刻被调用:

  • 组件卸载:当组件从 DOM 中移除时,React 会调用 useEffect 返回的清理函数。
  • 依赖项变更导致的重新执行:如果 useEffect 指定了依赖项,并且这些依赖项发生了变化,React 会在执行新的副作用函数之前调用旧的副作用函数返回的清理函数。

清理函数的作用
清理函数的主要作用是执行必要的清理工作,以防止内存泄漏或者其他副作用。这在处理订阅、定时器、DOM 引用等场景中尤为重要。

App.jsx


import React from "react"

import WindowTracker from "../public/components/WindowTracker";

export default function App(){


  const [show, setshow] = React.useState(true)

  function toggle(){
    setshow(prevShow => !prevShow)
  }

  return <div>
    <button onClick={toggle}>
      Toggle WindowTracker

    </button>
    {show && <WindowTracker />}
  </div>
  
}

WindowTracker.jsx

import React from "react"

export default function WindowTracker(){
    const [windowWidth, setWindowWidth] = React.useState(window.innerWidth)

    React.useEffect(() =>{
        function watchWidth(){
            console.log("Setting up...")
            setWindowWidth(windowWidth.innerWidth)
        }
    

        window.addEventListener("resize", watchWidth)

        return function(){
            console.log("Cleaning up...")
            window.removeEventListener("resize", watchWidth)
        }
    }, [])

    return (
        <h1>Window width: {windowWidth}</h1>
    )

}

6. async function

在 JavaScript 中,async function 是一种声明异步函数的方式。async 关键字用于声明一个函数是异步的,这意味着函数内部可以执行异步操作,如 Promise 或者异步函数调用,而不会阻塞代码的执行。
async 函数内部可以包含任意的代码,包括同步代码和异步代码。当 async 函数执行到一个 await 表达式时,会暂停执行,直到等待的 Promise 完成(无论是 fulfilled 还是 rejected),然后继续执行函数体内的剩余代码。

async function fetchData() {
  const data = await fetchSomeData(); // 等待 fetchSomeData() 完成
  return data;
}

在上面的例子中,fetchData 是一个 async 函数,它调用了 fetchSomeData 函数,并使用 await 关键字等待 fetchSomeData 返回的 Promise 完成。await 只能在 async 函数内部使用。