React Hooks(1) useState

1. Reactフックとは

useState の使用法について説明する前に、React Hook とは何かを見てみましょう。

フックは実際にはステートフルな機能コンポーネントです。クロージャは反応フックの中核です。

閉鎖

クロージャは、実行コンテキスト A と、A で作成された関数 B の 2 つの部分で構成される特別なオブジェクトです。Bの実行時にAの変数オブジェクトにアクセスするとクロージャが生成されます。

 // 执行上下文,这里暂时写为一个函数,它也可以指一个模块
 const A = () => {
    
    
   const a = "aaa" 
   const B = () => {
    
     
        // 注意这里可以修改a的值
      console.log(a)  
     // 当B执行时,如果访问了A中的变量,那就产生闭包,这里称A(执行上下文)为闭包
   }
 }

React コンポーネントを定義して他のモジュールで使用すると、クロージャが生成されます。

// 这里把A.js看成是一个模块
export const A = () => {
    
     
    const a = 'aaa'
 }
// B.js
import {
    
     A } from './A.js'
const B = () => {
    
     
    // 这里把B.js看成是另一个组件,引入A组件,并且访问A组件中的变量,此时形成闭包, B里可以修改a的值
    console.log(a) 
}

クロージャの特性により、A モジュール内の a 変数は永続化されるため、B 関数が再度実行されると、最後の B 関数実行終了時の a の値も取得できます。
クロージャの原則に基づいてカスタム useState を作成できます。

// state.js模块 对应上面的A.js
let state = null;

export const useState = (value) => {
    
    
    // 第一次调用的时候没有初始值,因此使用传入的初始值赋值
    state = state || value
    function dispatch(newValue) => {
    
    
        state = newValue
        
    }
    return [state, dispatch]
}

// 在其他模块中引入并使用 对应上面的B.js 相当于是一个hooks组件
import React from 'react'
import {
    
     useState } from './state'

export default function Demo() {
    
     
    const [count, setCount] = useState(0)
    return <button onClick={
    
    () => setCount(count + 1)}>{
    
    count}</button>}

React は、トップダウンの一方向データ フロー メソッドを使用して独自のデータと状態を管理します。データは親コンポーネントによってのみトリガーされ、子コンポーネントに渡されます。そのため、react では state と props が変更されるとコンポーネントが再レンダリングされ、親コンポーネントが変更された場合は、親コンポーネントの下にある子コンポーネントも再レンダリングされます。
レンダリングメソッド:
クラスコンポーネント: レンダリングメソッドを再実行;
機能コンポーネント: 関数全体を再実行;

二 useState()

useState() の主な機能は状態を保存することであり、デフォルト値であるパラメーターを受け取ります。これは配列を返します。最初の配列はデータで、2 番目の配列はデータを操作するメソッドです。
簡単な例を見てみましょう。

import React, {
    
     useState } from 'react';

function Bulbs() {
    
    
  const [on, setOn] = useState(false);

  const lightOn = () => setOn(true);
  const lightOff = () => setOn(false);

  //lightOn和lightOff实际上用lightSwitch一个方法就够了
  const lightSwitch = () => setOn(on => !on);

  return (
    <>
      <div className={
    
    on ? 'bulb-on' : 'bulb-off'} />
      <button onClick={
    
    lightOn}>开灯</button>
      <button onClick={
    
    lightOff}>关灯</button>
    </>
  );
}

1. 使用方法

(1) useState は現在の状態の初期値として値を受け取ります。コンポーネントが初めてレンダリングされるときにのみ実行されます。関数をパラメータとして渡すこともできます。
関数を渡す例を次に示します。

const a = 10
const b = 20
const [count, setCount] = useState(() => {
    
    
    return a + b
})

(2) コールバックを使用した状態更新

const [toggled, setToggled] = useState(false);
setToggled(toggled => !toggled);

const [count, setCount] = useState(0);
setCount(count => count + 1);

// 数组的修改要注意
const [items, setItems] = useState([]);
setItems(items => [...items, 'New Item']);

2. 注意すべき点

(1) useState() はトップレベルでのみ呼び出され、関数コンポーネントまたはカスタムフックの内部でのみ呼び出されます。ループ、条件分岐、入れ子関数では呼び出すことができません。
(2) 廃止された状態
クロージャは、外部スコープから変数を取り込む関数です。状態変数はレンダリング間で変化するため、クロージャは最新の状態値を持つ変数をキャプチャする必要があります。そうしないと、状態が古いという問題が発生する可能性があります。

function DelayedCount() {
    
    
  const [count, setCount] = useState(0);

  const handleClickAsync = () => {
    
    
    setTimeout(function delay() {
    
    
      setCount(count + 1);
    }, 3000);
  }

  return (
    <div>
      {
    
    count}
      <button onClick={
    
    handleClickAsync}>Increase async</button>
    </div>
  );
}

ボタンが素早く複数回クリックされ、count 変数に実際のクリック数が正しく記録されず、一部のクリックが食い込まれます。
この問題を解決するには、関数メソッドを使用してカウント状態を更新します。次のようにsetCount(count + 1);変更するだけです。setCount(count => count + 1);

おすすめ

転載: blog.csdn.net/LittleMoon_lyy/article/details/124518285