React learning le douzième jour React Hooks analyse les fonctionnalités après react16.8

Table des matières:

1 Connaître et expérimenter les crochets

2 État/Effet

3 Contexte/Réducteur

4 Rappel/Mémo

5 Ref/LayoutEffet

6 crochets personnalisés

Après cela, vous pouvez utiliser des crochets pour en développer davantage, mais vous devez toujours savoir comment utiliser les composants de classe.

1. Connaître et expérimenter les crochets

Les fonctions sont le défaut des composants :

1. La modification des variables dans le composant de fonction ne déclenchera pas le rendu pour re-rendre

2. Les conditions qui peuvent déclencher un nouveau rendu, car il n'y a pas d'endroit pour enregistrer la nouvelle valeur variable, la valeur finale de la variable rendue est toujours la valeur par défaut

3. Il n'y a pas de cycle de vie

 Inconvénients des composants de classe :

(1) Lorsque la logique est complexe, le code est pléthorique

(2) La classe elle-même est complexe, qu'est-ce que cela signifie

(3) Vous devez utiliser des fonctions d'ordre supérieur pour réaliser l'utilisation de certaines choses

 L'utilisation de crochets peut simplifier la quantité de code, avoir l'air concis et ne plus avoir ces problèmes de pointage

Les crochets doivent être utilisés au niveau supérieur de la fonction, sinon une erreur sera signalée

correct:

Erreur:

Les crochets ne peuvent pas être utilisés dans les composants de classe, ni les crochets dans d'autres fonctions ordinaires. Mais les crochets peuvent être utilisés dans les crochets personnalisés.

Les fonctions ordinaires utilisant des crochets signaleront une erreur :

Il est permis d'utiliser d'autres crochets dans les crochets personnalisés :

 

 

 

 

2. État/Effet

1. const [Le premier paramètre est la valeur de retour, le deuxième paramètre est la fonction d'origine pour réinitialiser la valeur stockée] = useState (valeur initiale) doit avoir une valeur entre parenthèses, sinon la valeur initiale est indéfinie

Le premier paramètre est similaire à this.state;, le deuxième paramètre est similaire à setState

(1) Lorsque la fonction est appelée, elle sera détruite et la variable à l'intérieur disparaîtra. useState équivaut à enregistrer cette variable dans une autre fonction de react, puis à la retirer et à la réutiliser, et à appeler la fonction pour modifier le la valeur de la variable est équivalente à Lors de l'appel de la fonction qui contient la variable

2. Les effets secondaires signifient certaines fonctions supplémentaires qui peuvent être utilisées une fois le rendu de la page terminé, telles que les requêtes réseau, le cycle de vie, les opérations dom, etc.

(1) useEffect (les effets secondaires doivent être placés dans un endroit séparé):

Les effets secondaires suivants ne sont pas placés dans un endroit séparé :

Les effets secondaires suivants sont placés dans des endroits séparés :

(2) Effacer certains événements d'écoute dans les effets secondaires (mécanisme d'effacement)

Notez que le code de useEffect sera exécuté une fois à chaque mise à jour des données, et (4) expliquera comment faire en sorte que le code de useEffect ne s'exécute qu'une seule fois.

 La façon d'annuler la surveillance est d'écrire une fonction de retour

(3) Plusieurs useEffects peuvent être utilisés dans un composant pour placer différents codes respectivement

(4) Optimisation des performances UseEffect, contrôle de l'exécution du rappel, de sorte que certaines choses ne soient exécutées qu'une seule fois ou modifiées par quelqu'un.

Si vous avez besoin de contrôler l'exécution d'un certain code à cause de ce qui change, écrivez un tableau dans le deuxième paramètre de useEffect, et écrivez qui est affecté par celui-ci dans le tableau :

Il vous suffit d'écrire un tableau vide [] dans le deuxième paramètre de useEffect pour l'exécuter une seule fois lorsque le composant est chargé, et peu importe qui change à l'avenir, la fonction encapsulée par useEffect ne sera pas exécutée :

 

 

 

 

三、Contexte/Réducteur

Les hooks suivants ont tendance à être utilisés dans des scénarios spéciaux, et useState et useEffect ci-dessus sont les éléments de base qui doivent être renvoyés.

1. L'utilisation de useContext :

(1) Créez un dossier de contexte et un fichier index.js :

(2) Le fichier index.js correspondant à App.jsx fournit les données :

(3) Utilisez les paramètres fournis dans le App.jsx enveloppé :

2, useReducer (comprendre)

Remplacement équivalent pour useState

Le scénario d'utilisation de useReducer est illustré dans la figure ci-dessous. Plusieurs paramètres peuvent être gérés en même temps, mais le code de modification des paramètres doit être placé dans le réducteur, ce qui n'est pas facile à utiliser :

 Comment utiliser useReducer :

import React, { memo, useReducer } from 'react'
// import { useState } from 'react'

function reducer(state, action) {
  switch(action.type) {
    case "increment":
      return { ...state, counter: state.counter + 1 }
    case "decrement":
      return { ...state, counter: state.counter - 1 }
    case "add_number":
      return { ...state, counter: state.counter + action.num }
    case "sub_number":
      return { ...state, counter: state.counter - action.num }
    default:
      return state
  }
}

// useReducer+Context => redux

const App = memo(() => {
  // const [count, setCount] = useState(0)
  const [state, dispatch] = useReducer(reducer, { counter: 0, friends: [], user: {} })

  // const [counter, setCounter] = useState()
  // const [friends, setFriends] = useState()
  // const [user, setUser] = useState()

  return (
    <div>
      {/* <h2>当前计数: {count}</h2>
      <button onClick={e => setCount(count+1)}>+1</button>
      <button onClick={e => setCount(count-1)}>-1</button>
      <button onClick={e => setCount(count+5)}>+5</button>
      <button onClick={e => setCount(count-5)}>-5</button>
      <button onClick={e => setCount(count+100)}>+100</button> */}

      <h2>当前计数: {state.counter}</h2>
      <button onClick={e => dispatch({type: "increment"})}>+1</button>
      <button onClick={e => dispatch({type: "decrement"})}>-1</button>
      <button onClick={e => dispatch({type: "add_number", num: 5})}>+5</button>
      <button onClick={e => dispatch({type: "sub_number", num: 5})}>-5</button>
      <button onClick={e => dispatch({type: "add_number", num: 100})}>+100</button>
    </div>
  )
})

export default App

 

4. Rappel/Mémo

Remarque : si vous ne comprenez vraiment pas, il vous suffit de savoir que lorsque le composant parent veut passer une fonction au composant enfant à l'avenir, il doit être enveloppé par useCallback.

1. useCallback est utilisé pour l'optimisation des performances

(1) Analyse de la raison : lorsqu'une fonction définie dans un composant fonctionnel est appelée et restituée, la fonction sera redéfinie, puis la fonction d'origine sera détruite.

 La fonction précédente est détruite

(2) L'utilisation de useCallback peut optimiser le code que vous utilisez à chaque fois ou la fonction enveloppée par le rappel d'origine, mais la fonction enveloppée sera toujours redéfinie à chaque fois que le composant fonctionnel sera rendu à nouveau, donc cela n'a aucun effet.

(3) Interruption de rappel :

(4) useCallback est généralement utilisé pour optimiser le moment où le composant parent transmet des fonctions au composant enfant, afin d'éviter que le composant parent ne laisse le composant enfant restituer et exécuter la fonction du composant enfant pour réduire les performances. La raison en est que s'il existe de nombreuses fonctions dans le composant enfant et que l'une des fonctions est transmise par le composant parent, alors lorsque le composant parent restitue, la fonction sera recréée et les accessoires du composant enfant seront obtenu à partir du composant parent. La fonction est également réacquise, le sous-composant est restitué et de nombreuses fonctions du sous-composant sont également recréées. Les performances baissent.

import React, { memo, useState, useCallback, useRef } from 'react'

// useCallback性能优化的点:
// 1.当需要将一个函数传递给子组件时, 最好使用useCallback进行优化, 将优化之后的函数, 传递给子组件

// props中的属性发生改变时, 组件本身就会被重新渲染
const HYHome = memo(function(props) {
  const { increment } = props
  console.log("HYHome被渲染")
  return (
    <div>
      <button onClick={increment}>increment+1</button>

      {/* 100个子组件 */}
    </div>
  )
})

const App = memo(function() {
  const [count, setCount] = useState(0)
  const [message, setMessage] = useState("hello")

  // 闭包陷阱: useCallback
  // const increment = useCallback(function foo() {
  //   console.log("increment")
  //   setCount(count+1)
  // }, [count])

  // 进一步的优化: 当count发生改变时, 也使用同一个函数(了解)
  // 做法一: 将count依赖移除掉, 缺点: 闭包陷阱
  // 做法二: useRef, 在组件多次渲染时, 返回的是同一个值
  const countRef = useRef()
  countRef.current = count
  const increment = useCallback(function foo() {
    console.log("increment")
    setCount(countRef.current + 1)
  }, [])

  // 普通的函数
  // const increment = () => {
  //   setCount(count+1)
  // }

  return (
    <div>
      <h2>计数: {count}</h2>
      <button onClick={increment}>+1</button>

      <HYHome increment={increment}/>

      <h2>message:{message}</h2>
      <button onClick={e => setMessage(Math.random())}>修改message</button>
    </div>
  )
})


// function foo(name) {
//   function bar() {
//     console.log(name)
//   }
//   return bar
// }

// const bar1 = foo("why")
// bar1() // why
// bar1() // why

// const bar2 = foo("kobe")
// bar2() // kobe

// bar1() // why

export default App

Remarque : La différence entre useCallback et usememo est que le premier renvoie une fonction, tandis que le second renvoie une valeur.

En termes simples, le rôle de useMemo est d'empêcher les composants fonctionnels de se restituer en raison d'un changement de paramètre tandis que d'autres fonctions exécutent plusieurs fonctions de manière répétée et d'éviter que les paramètres de type d'objet transmis aux sous-composants ne recréent des objets en raison du re-rendu des composants, et les sous-composants trouvent des modifications d'objet, les composants enfants restituent sans signification.

2. usememo est utilisé pour optimiser les composants de fonction individuels. Certaines fonctions modifient les variables et entraînent le rendu de l'ensemble du composant, et toutes les autres fonctions du composant sont réexécutées, ce qui gaspille les performances.

import React, { memo, useCallback } from 'react'
import { useMemo, useState } from 'react'


const HelloWorld = memo(function(props) {
  console.log("HelloWorld被渲染~")
  return <h2>Hello World</h2>
})


function calcNumTotal(num) {
  // console.log("calcNumTotal的计算过程被调用~")
  let total = 0
  for (let i = 1; i <= num; i++) {
    total += i
  }
  return total
}

const App = memo(() => {
  const [count, setCount] = useState(0)

  // const result = calcNumTotal(50)

  // 1.不依赖任何的值, 进行计算
  const result = useMemo(() => {
    return calcNumTotal(50)
  }, [])

  // 2.依赖count
  // const result = useMemo(() => {
  //   return calcNumTotal(count*2)
  // }, [count])

  // 3.useMemo和useCallback的对比
  function fn() {}
  // const increment = useCallback(fn, [])
  // const increment2 = useMemo(() => fn, [])


  // 4.使用useMemo对子组件渲染进行优化
  // const info = { name: "why", age: 18 }
  const info = useMemo(() => ({name: "why", age: 18}), [])

  return (
    <div>
      <h2>计算结果: {result}</h2>
      <h2>计数器: {count}</h2>
      <button onClick={e => setCount(count+1)}>+1</button>

      <HelloWorld result={result} info={info} />
    </div>
  )
})

export default App

 

五、Ref/LayoutEffect

1. useRef a deux usages :

(1) DOM contraignant

(2) Lier la valeur pour résoudre le piège de fermeture

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

const App = memo(() => {
  const titleRef = useRef()
  const inputRef = useRef()
  
  function showTitleDom() {
    console.log(titleRef.current)
    inputRef.current.focus()
  }

  return (
    <div>
      <h2 ref={titleRef}>Hello World</h2>
      <input type="text" ref={inputRef} />
      <button onClick={showTitleDom}>查看title的dom</button>
    </div>
  )
})

export default App
import React, { memo, useRef } from 'react'
import { useCallback } from 'react'
import { useState } from 'react'

let obj = null

const App = memo(() => {
  const [count, setCount] = useState(0)
  const nameRef = useRef()
  console.log(obj === nameRef)
  obj = nameRef

  // 通过useRef解决闭包陷阱
  const countRef = useRef()
  countRef.current = count

  const increment = useCallback(() => {
    setCount(countRef.current + 1)
  }, [])

  return (
    <div>
      <h2>Hello World: {count}</h2>
      <button onClick={e => setCount(count+1)}>+1</button>
      <button onClick={increment}>+1</button>
    </div>
  )
})

export default App

2, utilisezImperativeHandle

import React, { memo, useRef, forwardRef, useImperativeHandle } from 'react'

const HelloWorld = memo(forwardRef((props, ref) => {

  const inputRef = useRef()

  // 子组件对父组件传入的ref进行处理
  useImperativeHandle(ref, () => {
    return {
      focus() {
        console.log("focus")
        inputRef.current.focus()
      },
      setValue(value) {
        inputRef.current.value = value
      }
    }
  })

  return <input type="text" ref={inputRef}/>
}))


const App = memo(() => {
  const titleRef = useRef()
  const inputRef = useRef()

  function handleDOM() {
    // console.log(inputRef.current)
    inputRef.current.focus()
    // inputRef.current.value = ""
    inputRef.current.setValue("哈哈哈")
  }

  return (
    <div>
      <h2 ref={titleRef}>哈哈哈</h2>
      <HelloWorld ref={inputRef}/>
      <button onClick={handleDOM}>DOM操作</button>
    </div>
  )
})

export default App

3、utiliserLayoutEffect

(1) Le temps d'exécution de useLayoutEffect et useEffect est différent 

(2) useLayoutEffect peut éviter le scintillement de l'écran dans certains cas

Temps d'exécution:

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

const App = memo(() => {
  const [count, setCount] = useState(0)
  
  useLayoutEffect(() => {
    console.log("useLayoutEffect")
  })

  useEffect(() => {
    console.log("useEffect")
  })

  console.log("App render")

  return (
    <div>
      <h2>count: {count}</h2>
      <button onClick={e => setCount(count + 1)}>+1</button>
    </div>
  )
})

export default App

Basculer l'utilisation du numéroEffet :

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

const App = memo(() => {
  const [count, setCount] = useState(100)

  useEffect(() => {
    console.log("useEffect")
    if (count === 0) {
      setCount(Math.random() + 99)
    }
  })

  console.log("App render")

  return (
    <div>
      <h2>count: {count}</h2>
      <button onClick={e => setCount(0)}>设置为0</button>
    </div>
  )
})

export default App

Basculer les numéros -useLayoutEffect :

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

const App = memo(() => {
  const [count, setCount] = useState(100)

  useLayoutEffect(() => {
    console.log("useLayoutEffect")
    if (count === 0) {
      setCount(Math.random() + 99)
    }
  })

  console.log("App render")

  return (
    <div>
      <h2>count: {count}</h2>
      <button onClick={e => setCount(0)}>设置为0</button>
    </div>
  )
})

export default App

 

6. Utilisation de crochets personnalisés

 

Je suppose que tu aimes

Origine blog.csdn.net/weixin_56663198/article/details/129269951
conseillé
Classement