React Hook - explicação detalhada da função useEffecfa

Análise detalhada de useEffect

useEffecf uso básico

O livro continua com o anterior. No artigo anterior, explicamos o State Hook. Podemos usar este hook para definir o estado em componentes funcionais.

Sabemos que pode haver funções de ciclo de vida em componentes de classe, então como definir funções semelhantes ao ciclo de vida em componentes de função?

O Effect Hook permite que você conclua algumas funções semelhantes ao ciclo de vida em sala de aula;

De fato, semelhante às solicitações de rede, atualização manual do DOM e monitoramento de alguns eventos são alguns efeitos colaterais (efeitos colaterais) da atualização do DOM pelo React;

Assim, o Gancho que completa essas funções é chamado de Gancho de Efeito;

Suponha que agora tenhamos um requisito: o título na página sempre exibe o número do contador, que é implementado usando componentes de classe e Hook, respectivamente :

Implementação do componente de classe

import React, {
    
     PureComponent } from 'react'

export class App extends PureComponent {
    
    
  constructor() {
    
    
    super()

    this.state = {
    
    
      counter: 100
    }
  }

  // 进入页面时, 标题显示counter
  componentDidMount() {
    
    
    document.title = this.state.counter
  }

  // 数据发生变化时, 让标题一起变化
  componentDidUpdate() {
    
    
    document.title = this.state.counter
  }

  render() {
    
    
    const {
    
     counter } = this.state

    return (
      <div>
        <h2>{
    
    counter}</h2>
        <button onClick={
    
    () => this.setState({
    
    counter: counter+1})}>+1</button>
      </div>
    )
  }
}

export default App

Implementação do componente de função mais Hook:

  • Por meio do gancho useEffect, você pode dizer ao React que precisa executar determinadas operações após a renderização;
  • useEffect exige que passemos uma função callback, que será chamada de volta depois que o React terminar de atualizar o DOM ( ou seja, depois que o componente for renderizado );
  • 默认情况下, seja após a primeira renderização ou após cada atualização, esta função de retorno de chamada será executada; em geral, escrevemos efeitos colaterais nesta função de retorno de chamada (como solicitações de rede, operações DOM, monitoramento de eventos )

Portanto, deve-se notar que existem muitos ditados de que useEffect é usado para simular o ciclo de vida, mas não é; useEffect pode simular o ciclo de vida, mas sua principal função é realizar efeitos colaterais

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

const App = memo(() => {
    
    
  const [counter, setCounter] = useState(200)

  // useEffect传入一个回调函数, 在页面渲染完成后自动执行
  useEffect(() => {
    
    
    // 一般在该回调函数在编写副作用的代码(网络请求, 操作DOM, 事件监听)
    document.title = counter
  })

  return (
    <div>
      <h2>{
    
    counter}</h2>
      <button onClick={
    
    () => setCounter(counter+1)}>+1</button>
    </div>
  )
})

export default App

Efeitos colaterais claros (Efeito)

No processo de escrever componentes de classe, alguns códigos de efeitos colaterais precisam ser limpos em componentWillUnmount :

Por exemplo, chame manualmente a assinatura em nosso barramento de evento anterior ou Redux;

Todos precisam ter um cancelamento de inscrição correspondente em componentWillUnmount;

Como o Effect Hook simula o componenteWillUnmount?

O useEffect passado em 回调函数Asi pode ter um valor de retorno, que é outro回调函数B :

type EffectCallback = () => (void | (() => void | undefined));

Por que retornar uma função em vigor?

Este é um mecanismo de limpeza opcional para efeitos. Cada efeito pode retornar uma função de limpeza;

Então você pode 添加和移除juntar a lógica da assinatura;

Todos eles fazem parte do efeito;

Quando o React limpa o efeito?

O React fará uma operação de limpeza quando o componente for atualizado e desinstalado, cancelando o último monitoramento, deixando apenas o monitoramento atual;

Conforme aprendido anteriormente, os efeitos são executados em cada renderização;

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

const App = memo(() => {
    
    
  useEffect(() => {
    
    
    // 监听store数据发生改变
    const unsubscribe = store.subscribe(() => {
    
    

    })

    // 返回值是一个回调函数, 该回调函数在组件重新渲染或者要卸载时执行
    return () => {
    
    
      // 取消监听操作
      unsubscribe()
    }
  })

  return (
    <div>
      <h2>App</h2>
    </div>
  )
})

export default App

Usando múltiplos useEffects

Um dos propósitos de usar o Hook é resolver o problema de que o ciclo de vida de uma classe geralmente reúne muita lógica :

Por exemplo, solicitações de rede, monitoramento de eventos e modificação manual de DOM geralmente são colocados em componentDidMount;

Vários Hooks de efeito podem ser usados ​​em um componente de função e podemos separar a lógica em diferentes useEffects :

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

const App = memo(() => {
    
    
  // 监听的useEffect
  useEffect(() => {
    
    
    console.log("监听的代码逻辑")

    return () => {
    
    
      console.log("取消的监听代码逻辑")
    }
  })

  // 发送网络请求的useEffect
  useEffect(() => {
    
    
    console.log("网络请求的代码逻辑")
  })

  // 操作DOM的useEffect
  useEffect(() => {
    
    
    console.log("操作DOM的代码逻辑")
  })

  return (
    <div>
      App
    </div>
  )
})

export default App

O Hook nos permite separá-los de acordo com a finalidade do código, em vez de juntar muita lógica como uma função de ciclo de vida :

依次调用React seguirá cada efeito no componente na ordem da declaração de efeito ;


otimização de desempenho useEffect

Por padrão, a função callback de useEffect será reexecutada toda vez que for renderizada, mas isso causará dois problemas :

Alguns códigos que queremos executar apenas uma vez ( como requisições de rede, executar uma vez na primeira renderização de componentes, não precisa executar várias vezes ), semelhante ao que é feito em componentDidMount e componentWillUnmount na classe components;

Além disso, várias execuções também causarão certos problemas de desempenho;

Como decidimos quando useEffect deve ser executado e quando não deve ser executado?

useEffect na verdade tem dois parâmetros:

  • Parâmetro 1: A função callback a ser executada, já utilizamos este parâmetro e não diremos mais;
  • Parâmetro 2: É um tipo array, o que significa que o useEffect será reexecutado quando o estado mudar; ( quem será afetado por quem será reexecutado )

Exercícios de caso :

Efeito afetado pela contagem;

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

const App = memo(() => {
    
    
  const [counter, setCounter] = useState(100)
  
  // 发送网络请求的useEffect, 只有在counter发生改变时才会重新执行
  useEffect(() => {
    
    
    console.log("网络请求的代码逻辑")
  }, [counter])

  return (
    <div>
      <h2 onClick={
    
    () => setCounter(counter+1)}>{
    
    counter}</h2>
    </div>
  )
})

export default App

No entanto, se for uma função, 不希望依赖任何的内容时também podemos passar em uma matriz vazia [] :

Então, as duas funções de callback aqui correspondem às funções de ciclo de vida componentDidMount e componentWillUnmount, respectivamente;

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

const App = memo(() => {
    
    
  const [counter, setCounter] = useState(100)
  
  // 传入空数组表示不受任何数据依赖
  useEffect(() => {
    
    
    // 此时传入的参数一这个回调函数: 相当于componentDidMount
    console.log("监听的代码逻辑")

    // 参数一这个回调函数的返回值: 相当于componentWillUnmount
    return () => {
    
    
      console.log("取消的监听代码逻辑")
    }
  }, [])

  return (
    <div>
      <h2 onClick={
    
    () => setCounter(counter+1)}>{
    
    counter}</h2>
    </div>
  )
})

export default App

Resumo: useEffect pode simular o ciclo de vida do componente de classe anterior ( semelhante, mas não igual ) e é mais poderoso que o ciclo de vida original, azul é melhor que azul

Acho que você gosta

Origin blog.csdn.net/m0_71485750/article/details/126840653
Recomendado
Clasificación