2021/08/02

Reactの色々。ルーティングとか、コンポーネント分割とか。

@ 酒井悠宇

React

Reactを勉強していて、新しく学んだ概念がたくさんあるので、いい感じに覚えるために記事書いていきたいと思います。

Reactのルーティング

ルーティングって何?

ルーティング(routing)とは、通信において「あ〜、君はそこにいきたいのか〜。じゃあ、取り敢えずそっちの道を行きなよ」と、データさんのいくべき道を示してくれる仕組みのこと

このボタンを押したらこのページにいく。みたいなアレが実現しているのはルーティングがきちんと設定されているから。

react-router-dom

create-react-appで作成したプロジェクトにルーティングを設定する方法として、react-router-domを導入する方法がある。
使ってみるのが一番わかりやすいと思うので、実際にインストールしてみる。
create-react-appで作成したプロジェクトで、npmを使ってreact-router-domパッケージをインストール。

npm install react-router-dom

react-router-domでルーティングを実装する際にimportするものは主に4つ。

import { BrowserRouter, Switch, Route, Link } from 'react-router-dom'

こんな感じで使う

export const RouteTest = () => {
    return(
        <div>
            <Link to="/">トップ</Link> //パスネームを指定
            <Link to="/users">ユーザー一覧</Link>
            <BrowserRouter>
                <Switch>
                    <Route exact path="/"> //パスネームとページの紐付け
                        <Top/> //トップページのコンポーネント
                    </Route>
                    <Route path="/users">
                        <Users/> //ユーザー一覧のコンポーネント
                    </Route>
                </Switch>
            </BrowserRouter>
        </div>
    )
}

Link要素

パスを設定する

BrowserRouter要素

Switch要素をラップする。

Switch要素

Route要素をラップする。

Route要素

パスとページ(コンポーネント)を紐付けする作業を行う。

useHistory

ページ遷移を実現するフックとして、react-router-domにはuseHistoryというものも用意されている。

import { useHistory } from 'react-router-dom'

これを使用すると、Linkを使用せずにページ遷移を実現することができる。
javascript側からページ遷移の処理を行いたい(何か処理を行った後に自動でページを遷移したいみたいな)場合にuseHistoryを使用する。

export const Test = () => {
    const history = useHistory();
    const onClickRoot = () => history.push("/")
    return(
        <div>
            <button onClick={onClickRoot}>トップページに遷移</button>            
        </div>
    )
}

goBack関数を使えば一つ前のページに戻るみたいな挙動を実現できる。

export const Test = () => {
    const history = useHistory();
    const onClickBack = () => history.goBack();
    return(
        <div>
            <button onClick={onClickBack}>戻る</button>            
        </div>
    )
}

状態(state)を遷移先のページに渡すことも可能
ログインしているユーザー自身のページしか編集できないみたいな実装を行う時に使用

export const Test = () => {
    const history = useHistory();
    const onClickAdmin = () => history.push({ pathname: "/users", state: { isAdmin: true }})
    const onClickGeneral = () => history.push({ pathname: "/users", state: { isAdmin: false }})
    return(
        <div>
            <button onClick={onClickAdmin}>管理者ユーザー</button>
            <button onClick={onClickGeneral}>一般ユーザー</button>
        </div>
    )
}

useLocation

useHistoryで渡されたstateを受け取ることができる。

import { useLocation } from "react-router-dom";

使い方はこんな感じ

const { state } = useLocation();

遷移先のページでstateを受け取って、ユーザー本人かそうでないかを振り分けて表示を変えるみたいな時に使用。

コンポーネントの分割方法

Reactのコンポーネントを分割する際の考え方として、AtmicDesignというものがある。

AtmicDesignとは?

AtmicDesignとはBrad Frost氏が考案したデザインシステムで、画面要素を5段階に分け、それらを組み合わせることで、UIを実現するという考え方。

ReactやVue用というわけではなく、ただ単にそれらと相性がいい考え方だからよく使われるらしい。

5段階のコンポーネント

AtmicDesignでは、コンポーネントは五段階に分けられる。
ATOMS(原子、最小のコンポーネント)
MOLECULES(分子、ATOMSが組み合わさったもの)
ORGANISMS(有機体、MOLCULESが組み合わさったもの)
TEMPLATES(ページの枠を構成するコンポーネント)
PAGES(最終的に表示されるページ)

ATOMS

最も小さく、それ以上分解できない要素

  • ボタン
  • テキストボックス
  • アイコン 等...

MOLECULES

Atomsの組み合わせで意味を持つデザインパーツ

  • アイコン+メニュー
  • プロフィール画像+テキストボックス
  • アイコンセット 等...

ORGANISMS

AtomやMoleculesの組み合わせで構成される要素

  • ツイート入力エリア
  • サイドメニュー
  • 1つのツイートエリア

TEMPLATES

ページのレイアウトのみを表現する要素(実際のデータは持たない)

  • サイドメニュー
  • ツイートエリア
  • トピックエリアー
  • ヘッダー/フッター

PAGES

最終的に表示される1画面。

  • ページ遷移毎に表示される各画面


グローバルなstate管理

Reactのstateをpropsでコンポーネントに渡す際、ファイル階層が深くなると、コンポーネントからコンポーネントへデータのバケツリレーが起きてとても非効率。
なので、どのファイルからでも、どのコンポーネントからでも呼び出せるようなstateがあると便利だよね。みたいな考えから生まれたのがグローバルなstate管理という考え方。

createContext

グローバルなstate管理を行えるようにするためのコンポーネントを作るためのフック。

import { createContext } from 'react'

こんな感じで使う(今回はユーザーの情報を扱うコンポーネントを作成)

export const UserContext = createContext({});

export const UserProivider = (props) => {
    const { children } = props;

    const [userInfo, setUserInfo] = useState(null);
    return(
        <UserContext.Provider value={{ userInfo, setUserInfo }}>
            {children}
        </UserContext.Provider> 
    )
}

createContextに用意されているProviderというプロパティを使用し.Providerと繋げ、要素を囲むようにして使用する。

ソフトウェアやプログラミングの分野で、他のプログラムにデータや機能など何かを提供・供給するために作られたプログラムやプログラム部品(モジュールやオブジェクトなど)のことをプロバイダということがある

例えば、ここで作ったコンポーネントでApp.jsを囲ってやれば、その配下のコンポーネントは全てUserProviderにある情報を参照できるようになる。
今回の例では、valueに指定したstate{{ userInfo, setUserInfo }}を参照できるようになる。

function App() {
  return (
    <UserProivider>
      <Router/>
    </UserProivider>
  );
}

useContext

createContextで作成したコンポーネントの情報を受け取るためのフック

import { useContext } from 'react'

こんな感じで使用する

const { userInfo } = useContext(UserContext); //引数にはどのcontextを参照したいのかを指定

するとcreateContextで作成したコンポーネントのvalueに設定されてある値を参照できるようになる。
createContext, useContextを用いることで、グローバルなstate管理を行えるようになる。

今日はとりあえずここまでにします!
次はコンポーネントの再レンダリングについても書いていきたい!
ありがとうございました〜!

© 2021 powerd by UnReact