0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

グローバルなstateの管理をRecoilを使って超簡易版 @yukilulu0229

Posted at

インストール

npm i recoil

再レンダリングをある程度最適化してくれる

使い方

設定する

store/userState.jsx

import {atom} from "recoil"

export const userState = atom({
  key: "userState", // 名前を決めるファイル名を一緒にするのが望ましい
  default: {isAdmin: false}
})


範囲を選択する

App.jsx
import React from 'react'
import './App.css'
import {RecoilRoot} from "recoil";
import AtomicDesign from "./components/AtomicDesign.jsx";
import CssSettings from "./components/CssSettings.jsx";
import ReactRouter from "./components/ReactRouter.jsx";
import Rendering from "./components/Rendering.jsx";
import {BrowserRouter, Link, Route, Routes} from "react-router-dom";
import {UserProvider} from "./providers/UserProvider.jsx";

function App() {
  return (
    <div className="App">
      <RecoilRoot>
        <BrowserRouter>
          <Routes>
            <Route path="/Rendering" element={<Rendering />} />
            <Route path="/CssSettings" element={<CssSettings />} />
            <Route path="/ReactRouter/*" element={<ReactRouter />} />
            <Route path="/AtomicDesign/*" element={<AtomicDesign />} />
          </Routes>
        </BrowserRouter>
      </RecoilRoot>
    </div>
  )
}

export default App

useStateみたいのを定義

Users.jsx
import React, {useContext, useState} from 'react';
import {useRecoilState} from "recoil";
import {userState} from "../../store/userState.js";

const Users = () => {
  const [userInfo, setUserInfo] = useRecoilState(userState)
  console.log(userInfo);
  const isAdmin = userInfo ? userInfo.isAdmin : false
  const onClickSwitch = () => {
    setUserInfo({isAdmin: !isAdmin})
  }
  return (
    <>
      <SContainer>
        <SecondaryButton onClick={onClickSwitch}>切り替え</SecondaryButton>
      </SContainer>
    </>
  );
};

export default Users;

  • useRecoilStateがuseStateみたいなもの
  • userStateの定義を呼び出す
Top.jsx
import React, {useContext} from 'react';
import {useSetRecoilState} from "recoil";
import {userState} from "../../store/userState.js";
import {useNavigate} from "react-router-dom";

const Top = () => {
  const navigate = useNavigate();
  const setUserInfo = useSetRecoilState(userState)
  
  const onClickAdmin = () => {
    setUserInfo({isAdmin: true})
    navigate("/AtomicDesign/Users/")
  }
  const onClickGeneral = () => {
    setUserInfo({isAdmin: false})
    navigate("/AtomicDesign/Users/")
  }
  return (
    <DefaultLayout>
      <SContainer>
        <h2>Top Page</h2>
        <SecondaryButton onClick={onClickAdmin}>管理者ユーザー</SecondaryButton>
        <br/>
        <br/>
        <SecondaryButton onClick={onClickGeneral}>一般ユーザー</SecondaryButton>
      </SContainer>
    </DefaultLayout>
  );
};
export default Top;

  • useSetRecoilStateでuseStateのsetXxx側だけを呼び出す
  • 変更したいsetNameを呼び出してる

使いたい場所

import React, {memo, useContext} from 'react';
import {useRecoilValue} from "recoil";
import {userState} from "../../../store/userState.js";

const UserIconWithName = memo((props) => {
  const {image, name} = props
  const userInfo = useRecoilValue(userState)
  
  const isAdmin = userInfo ? userInfo.isAdmin : false
  return (
    <SContainer>
      <SImage src={image} alt="プロフィール" />
      <SName>{name}</SName>
      {isAdmin && <SEdit>編集</SEdit>}
    </SContainer>
  );
});

export default UserIconWithName;
  • useRecoilValueで使いたいの呼び出す
  • userStateを使うことを知らせる

useContextの場合

providerで定義する

  • UserContextを作成する
  • UserProviderを作成する
  • propsでchildrenを受け取ってUserContext.Providerで挟める形にする
  • state管理したいものを定義する 今回はUserInfo その際にusaStateを変更ができる形にする
  • valueでstateしたいものを渡す
providers/UserProvider.tsx

import React, {createContext, useState} from 'react';

export const UserContext = createContext({});

export const UserProvider = (props) => {
  const {children} = props
  const [userInfo, setUserInfo] = useState(null) // 初期値null
  return (
    <UserContext.Provider value={{userInfo, setUserInfo}}>
      {children}
    </UserContext.Provider>
  )
}

App.jsxに設定

App.jsx
import React from 'react'
import './App.css'
import AtomicDesign from "./components/AtomicDesign.jsx";
import CssSettings from "./components/CssSettings.jsx";
import ReactRouter from "./components/ReactRouter.jsx";
import Rendering from "./components/Rendering.jsx";
import {BrowserRouter, Link, Route, Routes} from "react-router-dom";
import {UserProvider} from "./providers/UserProvider.jsx";

function App() {
  return (
    <div className="App">
      <UserProvider>
        <BrowserRouter>
          <Routes>
            <Route path="/Rendering" element={<Rendering />} />
            <Route path="/CssSettings" element={<CssSettings />} />
            <Route path="/ReactRouter/*" element={<ReactRouter />} />
            <Route path="/AtomicDesign/*" element={<AtomicDesign />} />
          </Routes>
        </BrowserRouter>
      </UserProvider>
    </div>
  )
}

export default App

UserProviderが使用できる範囲指定する

使いたい場所

Top.jsx
import React, {useContext} from 'react';
import {UserContext} from "../../providers/UserProvider.jsx";
import SecondaryButton from "../atoms/button/SecondaryButton.jsx";
import DefaultLayout from "../templates/DefaultLayout.jsx";
import {useNavigate} from "react-router-dom";

const Top = () => {
  const navigate = useNavigate();
  const {setUserInfo} = useContext(UserContext)
  const onClickAdmin = () => {
    setUserInfo({isAdmin: true})
    navigate("/AtomicDesign/Users/")
  }
  const onClickGeneral = () => {
    setUserInfo({isAdmin: false})
    navigate("/AtomicDesign/Users/")
  }
  return (
    <DefaultLayout>
        <SecondaryButton onClick={onClickAdmin}>管理者ユーザー</SecondaryButton>
        <SecondaryButton onClick={onClickGeneral}>一般ユーザー</SecondaryButton>
    </DefaultLayout>
  );
};

export default Top;


  • useContextを使ってグローバルに読み込めるようにする
  • 今回使いたいUserContext作成させる
  • useStateのsetUserInfoで変更できるようにする

memoを使って再レンダリングの最適化をする

UserIconWithName.tsx

import React, {memo, useContext} from 'react';
import styled from "styled-components";
import {UserContext} from "../../../providers/UserProvider.jsx";

const UserIconWithName = memo((props) => {
  const {image, name} = props
  const {userInfo} = useContext(UserContext)
  const isAdmin = userInfo ? userInfo.isAdmin : false
  return (
    <SContainer>
      <SImage src={image} alt="プロフィール" />
      <SName>{name}</SName>
      {isAdmin && <SEdit>編集</SEdit>}
    </SContainer>
  );
});

export default UserIconWithName;

  • memoを使って再レンダリングが必要がないことを指定している
  • これによって最適化する
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?