4
头图

join us!

Mountain" , provides technical-related information and a series of basic articles for front-end developers. For a better user experience, please move to our official website novices (16100dd532d319 https://xhs-rookies.com/ ) to learn and get the latest articles in time.

"Code tailor" , if you are interested in our article or want to make some suggestions, follow Mountain" public account, contact us, you can also watch it on WeChat Our article. Every suggestion or approval is a great encouragement to us!

Preface

In this article, our main purpose is to understand the use of shared state hook (useEffect)

useEffect

definition

Effect Hook allows you to perform side-effect operations in function components. In other words, it can complete some functions similar to the life cycle in Class.

how to use

useEffect() is as follows.

useEffect(() => {
    dosomeing(); // 执行一些副作用操作
},[]);

useEffect requires parameters

  • The first parameter: The Hook receives a function that contains imperative and may have side-effect code.
  • The second parameter: the useEffect will be re-executed when the state

What did useEffect do?

Through useEffect of Hook , you can tell React to perform certain operations after rendering; and useEffect requires us to pass a function, React performs the update DOM operation. By default, no matter what After the component is rendered for the first time, or after the component is updated, this function will be executed. We can perform some work similar Class component in the function to be passed, such as: changing the DOM, adding subscriptions, and setting Timer, record log, etc. should know that these side-effect operations in the function component are not allowed before useEffect Hook

prompt

If you are familiar with the life cycle function of React class useEffect Hook as a combination of the three functions componentDidMount , componentDidUpdate and componentWillUnmount

Clear effect

In the Class component, we need to clear some side-effect codes in componentWillUnmount , such as our creation timer and clear timer. Similarly, when the function component is uninstalled, we also need to clear the resources such as subscription or timer ID created by effect . To achieve this, the useEffect function needs to return a clear function. The following is an example of creating a timer:

const [count, addCount] = useState(0)
const [timer, addTimer] = useState(1000)

useEffect(() => {
  const interval = setInterval(() => {
    // 创建计时器
    addCount((val) => val + 1)
  }, timer)
  return () => {
    // 返回清除函数
    clearInterval(interval) // 清除计时器
  }
})

To prevent memory leaks, the cleanup function will be executed before the component is unloaded. In addition, if the component repeatedly exaggerated (usually the case), then in the implementation of the next effect before, on a effect had been cleared . In the above example, it means that every update of the component will create a new timer. If you want to avoid triggering effect every time you update, you need to use the second parameter of useEffect

Conditional execution of effect

By default, effect will be executed after each round of component rendering is completed. In this case, once effect changes, it will be recreated.

However, doing so may be overkill in some scenarios. For example, in the timer example above, we do not need to create a new timer every time the component is updated, but only need to source prop it when 06100dd532d87f changes.

The second parameter accepted by useEffect used here, which is an array of values on effect The updated example is as follows:

const [count, addCount] = useState(0)
const [timer, addTimer] = useState(1000)

useEffect(() => {
  const interval = setInterval(() => {
    // 创建定时器
    addCount((val) => val + 1)
  }, timer)
  return () => {
    clearInterval(interval) // 清除定时器
  }
}, [count])

When the second parameter is passed in, the count changed. That is to say, useEffect will decide whether to execute this update according to the second parameter we passed in.

note

  • If you want to use this optimization, make sure that the array contains variable of all external and scope vary in effect in , or your code references to previously rendered the old variable.
  • If you want to execute an effect that runs only once (only executed when the component is mounted and unmounted), you can pass an empty array ( [] ) as the second parameter.

Comparison component

I believe you already useEffect something about 06100dd532da01, so let's use a simple example to feel the difference between Hook and Class

There is a simple timer that 1000ms at the time interval of 06100dd532da19 by default. After clicking the plus button, the time interval increases and the timer counts down.

Class component implementation

First, we need to declare a variable count in the class component to count, a variable timer to control the counting interval, every timer time, count plus one, and then add a button, each time you click, timer increase 1000ms . At the same time, the increase rate of count

class Example extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 0,
      timer: 1000,
    }
  }

  componentDidMount() {
    this.interval = setInterval(() => {
      // 创建定时器
      this.setState({
        count: this.state.count + 1,
      })
    }, this.state.timer)
  }
  componentDidUpdate() {
    clearInterval(this.interval) // 先清除上一个定时器
    this.interval = setInterval(() => {
      // 创建以 更新后的timer 计时间隔定时器
      this.setState({
        count: this.state.count + 1,
      })
    }, this.state.timer)
  }
  componentWillUnmount() {
    clearInterval(this.interval) // 卸载时清除定时器
  }

  render() {
    return (
      <div>
        <p>当前count值为:{this.state.count}</p>
        <p>当前计数时间间隔为:{this.state.timer}ms</p>
        <button onClick={() => this.setState({ timer: this.state.timer + 1000 })}>Click me</button>
      </div>
    )
  }
}

We can find that in this class, we need to write duplicate code in two life cycle functions. It is also necessary to clear the timer when the component is uninstalled. A large amount of duplicate code is very cumbersome. So what is the use of Effect Hook in the function component?

Use Effect Hook to achieve

import React, { useState, useEffect } from 'react'

function Example() {
  const [count, addCount] = useState(0)
  const [timer, addTimer] = useState(1000)

  useEffect(() => {
    const interval = setInterval(() => {
      addCount((val) => val + 1)
    }, timer)
    return () => {
      clearInterval(interval)
    }
  }, [count])

  return (
    <div>
      <p>当前count的值为:{count}</p>
      <p>当前计数时间间隔为: {timer}ms</p>
      <button onClick={() => addTimer((val) => val + 1000)}>Click me</button>
    </div>
  )
}

After reading this example, are you surprised to find that Class component is constructor functions written in the three life cycles are solved useEffect Does it look very streamlined. I believe you have the following questions:

  • What did useEffect

    By using this Hook , you can tell the React component to perform certain operations after rendering. React will save the function you passed (we call it "effect") and call it after DOM

  • Why call in the internal components useEffect ?

    The useEffect internal components so that we can put in effect direct access to the count state variable (or other props ).

  • useEffect be executed after every rendering?

    Yes, by default, it after the first rendering and after each update will be executed (you can control the rendering conditions by the second argument mentioned earlier). Moreover, React ensures that every time effect is DOM has been updated.

summary

  • useEffect Hook actually brings us the ability to handle side effects in function components. It is like a combination of the three functions componentDidMount , componentDidUpdate and componentWillUnmount
  • The life cycle of the useEffect Hook and Class useEffect after the DOM has been updated, componentDidMount is called immediately after the component is hung (inserted into the DOM tree), and componentDidUpdate() is called immediately after the update. This method will not be executed for the first rendering. componentWillUnmount() will be called directly before the component is unloaded and destroyed.
  • useEffect Hook the emergence of 06100dd532e097, component development will gradually be flooded with state logic and side effects. Each life cycle often contains some irrelevant logic. And its appearance helps us to better split these state logics, not forcing the division according to the life cycle, and adds many possibilities for development.

Preview of the next section

In the next section, we will introduce useRefs to everyone, so stay tuned!


小和山的菜鸟们
377 声望2.1k 粉丝

每日进步的菜鸟,分享前端学习手册,和有心学习前端技术的小伙伴们互相探讨,一同成长。