サイトアイコン 上尾市のWEBプログラマーによるブログ

「Reactハンズオンラーニング」の感想・備忘録2

「Reactハンズオンラーニング」の感想・備忘録1の続き

ステート管理

6.3.3 カスタムフック

例えば、以下のテキストボックスの記述は重複してしまう。

<input type="text" value={msg1} onChange={e=>setMsg1(e.target.value)}/>
<input type="text" value={msg2} onChange={e=>setMsg2(e.target.value)}/>

カスタムフックを使えば、重複したコードを切り出すことができる。
以下の例は、初期値を受け取り配列を返すフックである。
(配列の先頭要素はvalueとonChangeを持つオブジェクト、2番目はリセットするための関数)

import {useState} from 'react'

export const useInput = initialValue => {
  const [value, setValue] = useState(initialValue)
  return [
    {value, onChange: e=>setValue(e.target.value)},
    () => setValue(initialValue)
  ]
}

上記フックは以下のように使用する。

import {useInput} from './hooks'

function Form({handelSubmit}) {
  const [msg1Props, resetMsg1] = useInput("")
  const [msg2Props, resetMsg2] = useInput("")
  const submit = e => {
    e.preventDefault()
    handelSubmit(msg1Props.value, msg2Props.value);
    resetMsg1()
    resetMsg2()
  }
  return (
    <form onSubmit={submit}>
      <p><input {...msg1Props}/></p>
      <p><input {...msg2Props}/></p>
      <button>送信</button>
    </form>
  );
}

export default Form;

6.4.3 コンテキストとステートの併用

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import ColorProvider from './ColorProvider';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <ColorProvider>
      <App/>
    </ColorProvider>
  </React.StrictMode>
);
import {createContext, useState} from 'react'
import App from './App';

export const ColorContext = createContext({})
function ColorProvider({children}) {
  const [color, setColor] = useState("#f00")
  const setBlue = () => setColor("#00f")
  return (
    <ColorContext.Provider value={{color, setColor, setBlue}}>
      {children}
    </ColorContext.Provider>
  );
}
export default ColorProvider
import Form from './Form'

function App() {
  return (
    <Form/>
  );
}
export default App;
import {useContext} from 'react'
import {ColorContext} from './ColorProvider'

function Form() {
  const {color, setColor, setBlue} = useContext(ColorContext)
  return (
    <div>
      <p>color: {color}<button type="button" onClick={e => setColor("#0f0")}>greenに変更</button></p>
      <p><button type="button" onClick={e => setBlue()}>setBlue()</button></p>
    </div>
  );
}
export default Form;

6.4.4 コンテキストとカスタムフックの併用

import {createContext, useState, useContext} from 'react'
import App from './App';

const ColorContext = createContext({})
export const useColor = () => useContext(ColorContext)
function ColorProvider() {
  const [color, setColor] = useState("#f00")
  const setBlue = () => setColor("#00f")
  return (
    <ColorContext.Provider value={{color, setColor, setBlue}}>
      <App/>
    </ColorContext.Provider>
  );
}

export default ColorProvider

コンシューマーではuseContext、ColorContextのインポートが不要となり、useColorをインポートするだけとなる。

import {useColor} from './ColorProvider'

function Form({handleSubmit}) {
  const {color, setColor, setBlue} = useColor()
  return (
    <div>
      <p>color: {color}<button type="button" onClick={e => setColor("#0f0")}>greenに変更</button></p>
      <p><button type="button" onClick={e => setBlue()}>setBlue()</button></p>
    </div>
  );
}

export default Form;
モバイルバージョンを終了