初心者のための反応フック



フックとは
反応フックは、アンカーのようなものです(船と海の床を取り付けるために海で低下するものと同じように)反応状態(海の床)と機能的なコンポーネントのライフサイクル機能(船)の間.
  • クラスベースのコンポーネントではなく、関数ベースのコンポーネントだけで動作します.
  • 両方の矢印と通常の機能コンポーネントの作品
  • ループ、条件、ネストした関数の中でフックをネストできません
  • useState() useState フックは、変数の状態を設定し、自動的に新しい状態でDOMを更新する機能を提供します


    インポート方法
    import React, {useState} from "react";
    // or 
    React.useState;
    

    useState
    import React, { useState } from 'react'
    
    let count1 = 0;
    
    function App() {
    
      const [count, setCount] = useState(0);
    
      let count2 = 0;
    
      return (
        <div className='container mt-3'>
          <h3>Hello World to React Hooks</h3>
    
          <h4>Count : {count}</h4>
          <h4>Count1 : {count1}</h4>
          <h4>Count2 : {count2}</h4>
    
          <button className='btn btn-info' onClick={() => {
            setCount(count + 1);
    
            console.log(`count : ${count} | count1 : ${count1}  count2 :${count2}`);
    
            count1 = count1 + 1;
            count2 = count2 + 1;
          }} >Add here</button>
        </div>
      )
    }
    
    export default App
    

    このコードではcount and count1 両方とも変数として更新されますDOM . でもcount2 は常に1であるbutton.onClick ) 任意のデータが反応コンポーネントで変更されるたびに、コンポーネント全体が再描画されます.これがコンポーネントの存在理由です.
    今、あなたは尋ねるかもしれません、我々はグローバル状態で変数を宣言して、使用しないでuseState . すべてのプログラミング言語における大域変数をよく宣言することは、いくつかの場合を除いて悪い慣習とみなされる.参照
  • https://www.tutorialspoint.com/why-are-global-variables-bad-in-c-cplusplus

  • useState コンポーネントが再レンダリングされても一貫性のない状態を提供します.
    useState オブジェクト
    import React, { useState } from 'react'
    
    function App() {
    
      const [{ counter1, counter2 }, setCounter] = useState({ counter1: 0, counter2: 20 })
    
      return (
        <div className='container mt-3'>
          <div className='container'>
    
            <h3>Counter1 : {counter1}</h3>
            <h3>Counter2 : {counter2}</h3>
    
    {/* this doesnt not work becuz whenever you update state, you need to update the whole object */}
    {/* Over here, we havent included the counter2 in the setCounter function. */}
    
            <button className="btn btn-primary" onClick={() =>
              setCounter(currentState => ({ counter1: currentState.counter1 + 1 }))}>Add</button> &nbsp;
    
    {/* this will also not work because spread operator in objects comes first 
        unlike in functions, where spread operator comes last. */}
    
    {/* Correct Code */}
                    <button className="btn btn-danger" onClick={() => setCounter(currentState => ({
              ...currentState,          
              counter1: currentState.counter1 - 1,
            }))}>Subtract</button
    
          </div>
        </div>
      )
    }
    
    export default App;
    

    別の例useState()
    import React, { useState } from "react";
    
    function App() {
    
      const [name, setName] = useState(localStorage.getItem("name") || "");
    
      return (
        <div className="App">
    
          <div className="container mt-3">
            <input name="name" value={name} onChange={e => {
              setName(e.target.value)
              localStorage.setItem("name", e.target.value)
            }} className='form-control' />
    
            <h3>Name : {name}</h3>
          </div>
    
        </div >
      );
    }
    
    export default App;
    
    useEffect()
  • コンポーネントがレンダリングされるたびに実行されます
  • useEffect 渡されたときには依存関係はないcomponentDidMount
  • からの矢印関数を返すuseEffect クリーンアップ機能
  • 多くuseEffect フックは1つのコンポーネントに共存できます
  • import React, { useState, useEffect } from "react";
    import HelloWorld from "./component/HelloWorld";
    
    function App() {
    
      const [count, setCount] = useState(0);
      const [showComp, setComp] = useState(false);
    
      useEffect(() => {
        console.log("Rendering ...")
      })
    
      return (
        <div className="App">
    
          <br />
    
          <div className='container mt-3'>
            <h3>Count : {count}</h3>
            <button className="btn btn-primary" onClick={() => setCount(count + 1)}>Add</button> &nbsp;
          </div>
    
          <br />
    
          <div className='container'>
            <button onClick={() => setComp(!showComp)} className="btn btn-info"> toggle </button>
            {showComp && <HelloWorld />}
          </div>
    
        </div >
      );
    }
    
    export default App;
    
    // in src/component/HelloWorld.jsx
    
    import React from 'react'
    
    function HelloWorld() {
        return (
            <div className='container mt-3'>
                <h2>HelloWorld component</h2>
            </div>
        )
    }
    
    export default HelloWorld
    

    コードを実行し、コンソールを見てください.カウンタをインクリメントしたり、コンポーネントをトグルするかどうかは問題ではありません.
    これを止めるにはuseEffect 次のとおり
    useEffect(() => {
        console.log("Rendering ...")
    }, [])
    
    これで、ページを更新するときだけレンダリングがコンソール上で印刷されます.次のようにコードを変更してみてください
    useEffect(() => {
        console.log("Rendering ...")
    }, [count])
    
    現在、コンポーネントが再表示されます
    これが何useEffect 必要に応じて、コンポーネントを更新/レンダリングするだけです.コンポーネントをクリーンアップする方法もあります.変更するHelloWorld.jsx
    import React from 'react'
    
    function HelloWorld() {
    
        React.useEffect(() => {
            console.log('HelloWorld')
            return () => {
                console.log('GoodByeWorld')
            }
        }, [])
    
        return (
            <div className='container mt-3'>
                <h2>HelloWorld component</h2>
            </div>
        )
    }
    
    export default HelloWorld
    
    // and App.jsx
    
    useEffect(() => {
        console.log("Rendering ...")
    },[])
    
    スイッチを切り替えるには、コンポーネントを持つメッセージが読み込まれますDOMunmounting . これはcomponentWillMount and componentWillUnmount useRef単純にいくつかのHTML要素を置くか、またはフォーカスするコンポーネントを反応させたいとき
    このコードの実行
    import React, { useRef } from "react";
    
    function App() {
    
      const inputRef = useRef();
    
      return (
        <div className="App">
    
          <div className="container mt-3">
    
            <input ref={inputRef} name="name" value={name} onChange={e => {
              setName(e.target.value)
              localStorage.setItem("name", e.target.value)
            }}
              className='form-control'
            />
    
            <br />
    
            <button onClick={() => {
              inputRef.current.focus();
            }} className="btn btn-success" >Get focus</button>
    
          </div>
    
        </div>
      );
    }
    
    export default App;
    

    useReducerダイアグラム説明

    import React, { useReducer } from "react";
    
    function reducer(state, action) {
      switch (action.type) {
        case 'increment': return state + 1;
        case 'decrement': return state - 1;
        default: return state;
      }
    }
    
    function App() {
    
      const [count, dispatch] = useReducer(reducer, 0);
    
      return (
        <div className="App">
    
          <div className='container' >
            <h2> count : {count} </h2>
            <button onClick={() => dispatch({ type: 'increment' })} className='btn btn-primary' > increment </button>
            <button onClick={() => dispatch({ type: 'decrement' })} className='btn btn-danger' > increment </button>
    
          </div>
    
        </div >
      );
    }
    
    export default App;
    
    useContextダイアグラム説明

    // App.js
    import React from 'react'
    import HelloWorld from "./components/HelloWorld"
    import About from './component/About'
    import { UserContext } from './UserContext'
    
    function App() {
      return (
        <div>
          <UserContext.Provider value='super man'>
            <HelloWorld />
          </UserContext.Provider>
        </div>
      )
    }
    
    export default App
    
    // Hello World component
    
    import React, { useContext } from 'react'
    import { UserContext } from '../UserContext'
    
    function HelloWorld() {
    
        const msg = useContext(UserContext);
    
        return (
            <div className='container mt-3'>
                <h3>HelloWorld component : {msg}</h3>
            </div>
        )
    }
    
    export default HelloWorld
    
    // About component
    
    import React, { useContext } from 'react'
    import { UserContext } from '../UserContext'
    
    function About() {
    
        const msg = useContext(UserContext);
    
        return (
            <div className='container mt-3'>
                <h3>About component : {msg}</h3>
            </div>
        )
    }
    
    export default About
    
    // Usercontext.js 
    
    import { createContext } from "react";
    
    export const UserContext = createContext(null);
    
    useMemoメモまたはmemoizationは、何度も何度もそれを計算する代わりに何かについて覚えているときですuseMemo 反応では高価である関数のために使用され、我々はそれらを何度も何度も実行する必要はありません.似ているuseEffect しかし、UseEffectはコンポーネントライフサイクルの状態を管理するために使用されますが、それらは非常にsimiliarです.
    import React from 'react'
    
    function expensivePhoneFunc (product) {
      console.log("expensivePhoneFunc")
      return product[0];
    }
    
    function App() {
    
      let product = [{
        name: 'Phone XL',
        price: 100
      },
      {
        name: 'Phone Mini',
        price: 80
      },
      {
        name: 'Phone Standard',
        price: 60
      }]
    
      const [count , setCount] = React.useState(0);
    
      const expensivePhone = React.useMemo( () => {
        return expensivePhoneFunc(product);
      },[])
    
      return (
        <div className='container mt-3'>
          <h3>Product : {expensivePhone.name}</h3>
          <h4>Price : {expensivePhone.price}</h4>
          <br />
          <h3>Count : {count}</h3>
          <button className='btn btn-primary' onClick={() => setCount(count + 1)}>+</button>
        </div>
      )
    }
    
    export default App
    
    useCallbackそれはuseMemo 関数以外の関数ではなく、結果を返します.関数を繰り返し実行する代わりに.そのほとんどはUSememoとともに使用されます.
    import React, {useCallback} from 'react'
    import HelloWorld from './component/HelloWorld'
    
    function App() {
    
      const [count, setCount] = React.useState(0);
    
      const increment = useCallback(() => {
        setCount(c => c + 1);
      }, [setCount]);
    
    
      return (
        <div>
          <HelloWorld increment={increment} />
          <h3>Count : {count}</h3>
        </div>
      )
    }
    
    export default App
    
    // HelloWorld.jsx
    
    import React from 'react'
    
    const HelloWorld = React.memo(({ increment }) => {
    
        console.log("hello")
    
        return (
            <div className='container mt-3'>
                <h3>HelloWorld component</h3>
                <button onClick={increment}>Hello World</button>
            </div>
        )
    })
    
    export default HelloWorld