Reactを学ぶ中で必ず押さえておきたいこと②

JavaScript

0. はじめに

Reactについて、勉強したことを備忘録として限定記事でまとめていたのですが、暇だったので公開記事にしました。

※2018年に書いた記事:Reactを学ぶ中で必ず押さえておきたいこと①

1. Reactとは

  • UIコンポーネントを作成するためのライブラリことやな。
  • Facebook社が開発しているから、期待値大やな。
  • Reactを使うにあたり、仮想DOM、JSX、コンポーネント・・・といったワードが20000%の確率で出てくるんやな。

2. 仮想DOM

  • そもそもDOMは、Document Object Modelの略やな。
  • つまりは、HTMLにアクセスする窓口のことやな。
  • DOMを直接更新する場合、DOMが変更されるたびにブラウザがHTMLを解析してレンダリングするから、コストが高いんやな。
  • 仮想DOMでは、ページ変更前と変更後の仮想DOMを比較して、差分箇所を見つけて、リアルDOMに反映してくれるんやな。だからパフォーマンスが出るみたいやな。

3. JSX

  • JavaScriptの拡張言語で、HTMLライクな記述ができるようになるんやな。
  • 以下のイメージやな。
return (
  React.createElement(
    'button',
    {className: 'info'},
    onClick: test
    'ぼたん');
);
return (
  <button className="info" onClick={test}>ぼたん</button>
);
  • 「JSだと」みたいに、React.createElementとか書いても、直感的じゃないから分かりにくいんやな。
  • JSXは、結局はコンパイル時にReact要素(React.createElement)に変換される仕組みみたいやな。
  • {}の中に変数を使えるんやな。
  • タグを階層構成で書く感じやな。
  • ただ、最上位のタグは1つにせんとあかんから、<>で囲めばいいんやな。
    <div>で囲ってもいいけど、HTMLで見たときに余計な<div>タグが出てまうんやな。
return (
  <>
    <button>ぼたん1</button>
    <button>ぼたん2</button>
  </>
);

4. コンポーネント

  • UIの部品のことやな。
  • コンポーネントっていうのは、見た目だけでなく、機能(○○を更新とか)も含んでのことを言うんやな。
  • 部品化することで、再利用しやすくなるんやな。オブジェクト指向みたいなもんやな。
  • 1コンポーネント1ファイルで書くのがいいみたいやな。
  • クラスコンポーネント関数コンポーネントに分類できるんやな。
  • 以下のイメージやな。
class Button extends React.Component {
    render() {
        return <button>...</button>
    }
}
const Button = (props) => {
    return <button>...</button>
}
  • コンポーネントを組み合わせて画面を作っていくんやな。
  • コンポーネントは親子関係にして作ってくんやな。親コンポーネント-子コンポーネントってことやな。
  • 親コンポーネントから子コンポーネントにデータを受け渡すには、Propsっていう仕組みを使うんやな。
  • Propsを使うことで、子コンポーネントで表示する値を変更できる(=固定にしなくていい)わけやな。
  • Propsでは関数を渡したりもできるんやな。
    例えば、ボタンクリックされたときに、子コンポーネントで値変更して、結果を親コンポーネントのstateを更新するときとかに使うんやな。

5. ライフサイクル

  • ライフサイクルとは、コンポーネントが生成されてから破棄されるまでの期間のことやな。
  • 以下のライフサイクルに分けられるみたいやな。シンプルやな。
    • Mounting・・・コンポーネントが生成される期間。
    • Updating・・・コンポーネントが変更される期間。
    • Unmounting・・・コンポーネントが破棄される期間。

6. React Hooks

  • React 16.8(2020年2月)からReactに追加された機能やな。
  • これを使う事で、関数コンポーネントでもstateを扱うことが出来る様になったんやな。
  • React Hooksは、基本フックとしてuseState・useEffect・useContextがあるみたいやな。
    それ以外にも、useReducer・useCallback・useMemo・useRef・useImperativeHandle・useLayoutEffect・useDebugValueがあるみたいやな。
    とりあえず基本フックのみ記載するかな。

6-1. useState

  • 状態の定義や更新ができるんやな。
  • つまり、コンポーネント内の値を書き換えたいときに使えるんやな。
  • ちなみに、stateが変更されされたり、propsが変更されたときに、コンポーネントが再描画されるんやな。
  • useStateのsetを呼びだす際は、prevStateを使うことで、更新前の値を使用できるんやな。
  • useStateの使用方法は以下のイメージやな。
import { useState } from 'react'

export const Compornent = () => {

  // state・・・現在の状態
  // setState・・・更新関数
  // 0・・・初期値
  const[count, setCount] = useState(0);

  const countUp = () => {

    // こっちやと「今画面に出てる値+1」をする
    // なので連打でボタン押下したとき等、カウントが合わなくなる可能性がある
    // setCount(count + 1);

    // こっちやと「変更前の値+1」してくれる
    // 連打でボタン押下したときも問題ない
    setCount(prev => prev + 1);
  }

  return (
    <>
      <input type="text" value={count}/>
      <button onClick={countUp}>+</button>
    </>
  )
}

6-2. useEffect

  • useEffectは、レンダリングのタイミングで呼び出される処理のことやな。
  • レンダリングに関係ない処理って意味で、副作用って呼ばれてるみたいやな。
  • レンダリング後に、apiを呼び出したり、DB処理をしたい場合とかによく使われるみたいやな。
  • useEffectが呼び出されるタイミングってのは、制御できるんやな。
  • useEffectの使用方法は以下のイメージやな。
import { CompornentB } from './CompornentB'
import { useState, useEffect } from 'react'

export const CompornentA = () => {

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

  const countUp = () => {
    setCount(prev => prev + 1);
  }

  // 毎回のレンダリンで呼ばれる
  useEffect(() => {
    console.log("--- 毎回 ---")
    console.log(count)
  })

  // 初回のレンダリングのみ呼ばれる
  useEffect(() => {
    console.log("--- 初回 ---")
    console.log(count)
  }, [])

  // countが変更された場合のみ呼ばれる
  useEffect(() => {
    console.log("--- Count変更時 ---")
    console.log(count)
  }, [count])

  // レンダリングされる前に呼ばれる
  useEffect(() => {
    return () => {
      console.log("--- レンダリング前 ---")
      console.log(count)
   }
  })

  return (
    <>
      <input type="text" value={count}/>
      <button onClick={countUp}>+</button>
    </>
  )
}


6-3. useContex

  • Storeが簡単に作れるようになる仕組みやな。
  • コンポーネント間でデータの受け渡しができるようになるんやけど、Propsみたいに「親から子へ」っていう制約がなくなるんやな。
  • つまり、Storeを使うことで、親から孫へデータを受け渡しできたりするんやな。というか、アプリケーション全体で使いまわせるんやな。
  • useContexの使用方法は以下のイメージやな。
import '../styles/globals.css'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <>
      <label>--- appです ---</label>
      <br/>
      <Component {...pageProps} />
    </>
    ) 
}
export default MyApp
import type { NextPage } from 'next'
import { CompornentA } from "./CompornentA"
import { TestContext } from "./store";

const Home: NextPage = () => {
  return (
    <TestContext.Provider value={{id : "123456"}}>
    <label>--- indexです ---</label>
    <br/>
    <CompornentA/>
    </TestContext.Provider>
  )
}

export default Home
import { CompornentB } from './CompornentB'

export const CompornentA = () => {
  return (
    <>
      <label>--- CompornentAです ---</label>
      <br/>
      <CompornentB/>
    </>
  )
}
import { useTestContext } from "./store";

export const CompornentB = () => {

  const {id} = useTestContext();

  return (
    <>
      <label>--- CompornentBです ---</label>
      <br/>
      <label>indexで設定した「{id}」を、CompornentBで表示しています</label>
    </>
  )
}
import { useContext, createContext, useState } from "react"

type ContextType = {
  id: string
};

const testContext: ContextType = {
  id: ""
};

export const TestContext = createContext(testContext);

export function useTestContext() {
  return useContext(TestContext);
}