LoginSignup
0
0

React 朝の体操

Posted at

はじめに

普段は主にバックエンド側を担当していて、フロントは必要に応じて JavaScript、HTML、CSS をいじるくらい。
React はやっておいた方がいいかなと思って、三目並べのチュートリアルに取り組んだり、Udemy、インターネットの記事などを見たり。
実際やってみると React はユニークで面白いなと思いつつ、他のことを勉強していたり、今は業務でも使わないし、少し時間が経つと細かいことを忘れてしまいがち。。
それで、以下のようなことを考えました。

  • 三目並べよりもっと簡易に React の練習ができるトレーニングメニューを作って、繰り返しやったら身につくのでは?

そんな思いから、朝のラジオ対応くらいの感覚でできればという意味を込めて「React 朝の体操」というの練習メニューを作ってみました。

対象とする人

  • React に習熟したい(React の説明はしないです。自身の血・肉にしたい人を想定)
  • なんでもいいから、React の基本的な機能を使ってみたい

「React 朝の体操」のありか

GitHub に置きました。
ダウンロードまたはクローンして使ってください。
https://github.com/y74h1116/react-taiso
※README.md にコンテナの起動方法を記載してあります。

動作環境

Dockerが動いて、Webブラウザがあれば動くと思います。
(こちらでは Mac、WSL で動かしています。)
また、Dockerを使わなくても、オンラインの開発環境サービス、例えば CodeSandbox などでもできるのではと思っています。

React 朝の体操の内容紹介

前述の GitHub リポジトリに README.md に朝の体操メニューを記載してありますので、その内容に従ってソースコードに追加していきます。
React のデフォルト画面に追加していきます。
トレーニングなので、見た目(デザインやCSS)や変数名にはあまり気を使わずガシガシ打ち込む感じです。

  • jsx を使ってみる
    002_hello.png
    下記 Hello001.tsx が実装例です。(ファイル名や表示テキストに001とつけるのは、繰り返し練習する場合、2回目は 002 にすると干渉せずにファイル追加できるためです。)
src/Hello001.tsx
+ import { FC } from "react";
+
+ export const Hello001:FC = () => {
+    return (
+        <p>hello 001</p>
+    );
+ };

Hello001 を表示するため、App.tsx の jsx に <Hello001/> を追加します。

src/App.tsx
  import reactLogo from './assets/react.svg'
  import viteLogo from '/vite.svg'
  import './App.css'
+ import { Hello001 } from './Hello001'

  function App() {
    const [count, setCount] = useState(0)

    return (
      <>
+       <Hello001/>
        <div>
    以下略
  • Hello001 に枠をつける
    003_border.png
    border を指定します。(solidにした)
src/Hello001.tsx
import { FC } from "react";

export const Hello001:FC = () => {
+    const style = {border: 'solid'};
     return (
+        <div style={style}>
             <p>hello 001</p>
+        </div>
    );
};
  • useState を使ってみる
    004_input_text.png
    単純に、テキストボックスのコンポーネントで useState を呼び出すのと onChange のハンドラ関数を定義します。
src/Hello001Text.tsx
+ import { FC, useState } from "react";
+ 
+ export const Hello001Text:FC = () => {
+     const [strInput, setStrInput] = useState('');
+ 
+     const onChangeHandler = (event: React.ChangeEvent<HTMLInputElement>) => {
+         setStrInput(event.target.value);
+     };
+ 
+     return (
+         <input type="text" value={strInput} onChange={onChangeHandler}/>
+     );
+ };

Hello001 に追加します。

src/Hello001.tsx
  import { FC } from "react";
+ import { Hello001Text } from "./Hello001Text";

  export const Hello001:FC = () => {
      const style = {border: 'solid'};
      return (
          <div style={style}>
              <p>hello 001</p>
+             <Hello001Text/>
          </div>
      );
  };
  • useReducer を使ってみる
    005_useReducer.png
    ここでは、テキストボックスの内容が変化したら reducer に追加していくようにしました。
    テキストボックスの下に表示してます。(テキストの履歴のようになる)
src/Hello001Text.tsx
  import { FC, useState } from "react";
+ import { FC, useReducer, useState } from "react";

  export const Hello001Text:FC = () => {
      const [strInput, setStrInput] = useState('');

+     const reducerFunc = (state:string, action:string) => {
+         return state + ' => ' + action;
+     };
+     const [reducerState, dispatchFunc] = useReducer(reducerFunc, strInput);

      const onChangeHandler = (event: React.ChangeEvent<HTMLInputElement>) => {
          setStrInput(event.target.value);
+         dispatchFunc(event.target.value);
      };

      return (
+         <div>
              <input type="text" value={strInput} onChange={onChangeHandler}/>
+             <p>{reducerState}</p>
+         </div>
      );
  };

  • Recoil を使う準備
    RecoilRoot を追加します。
src/Hello001.tsx
  import { FC } from "react";
  import { Hello001Text } from "./Hello001Text";
+ import { RecoilRoot } from "recoil";
  
  export const Hello001:FC = () => {
      const style = {border: 'solid'};
      return (
          <div style={style}>
              <p>hello 001</p>
              <Hello001Text/>
+             <RecoilRoot>
+             </RecoilRoot>
          </div>
      );
  };
  • Recoil の Atom を使ってみる
    jsx を使っていないので、拡張子は .ts にしました。
    キーなどもあまりこだわらず、ファイル名と一緒にしておきます。
src/Hello001Atom.ts
+ import { atom } from "recoil";
+ 
+ export const Hello001Atom = atom({
+     key: "Hello001Atom",
+     default: 'a',
+ });

  • atom の値を表示する関数コンポーネントを追加する
    008_atom.png
    単純に atom の値を取得して出力します。
src/Hello001Show.tsx
+ import { FC } from "react";
+ import { useRecoilValue } from "recoil";
+ import { Hello001Atom } from "./Hello001Atom";
+ 
+ export const Hello001Show:FC = () => {
+     const strAtom = useRecoilValue(Hello001Atom);
+     return (
+         <p>{strAtom}</p>
+     );
+ };

RecoilRoot の中に配置します。

src/Hello001.tsx
  import { FC } from "react";
  import { Hello001Text } from "./Hello001Text";
  import { RecoilRoot } from "recoil";
+ import { Hello001Show } from "./Hello001Show";

  export const Hello001:FC = () => {
      const style = {border: 'solid'};
      return (
          <div style={style}>
              <p>hello 001</p>
              <Hello001Text/>
              <RecoilRoot>
+                 <Hello001Show/>
              </RecoilRoot>
          </div>
      );
  };

  • atom の値を更新してみる
    009_button.png
    ボタンをクリックしたら、atom の文字列を増やすようにしてみました。
src/Hello001Button.tsx
+ import { FC } from "react";
+ import { useRecoilState } from "recoil";
+ import { Hello001Atom } from "./Hello001Atom";
+ 
+ export const Hello001Button:FC = () => {
+     const [strAtom, setStrAtom] = useRecoilState(Hello001Atom);
+ 
+     const onClickHandler = () => {
+         setStrAtom(strAtom + ',a');
+     }; 
+ 
+     return (
+         <button onClick={onClickHandler}>ボタン</button>
+     );
+ };

ボタンも RecoilRoot の中に配置することを忘れずに。

src/Hello001.tsx
  import { FC } from "react";
  import { Hello001Text } from "./Hello001Text";
  import { RecoilRoot } from "recoil";
  import { Hello001Show } from "./Hello001Show";
+ import { Hello001Button } from "./Hello001Button";

  export const Hello001:FC = () => {
      const style = {border: 'solid'};
      return (
          <div style={style}>
              <p>hello 001</p>
              <Hello001Text/>
              <RecoilRoot>
                  <Hello001Show/>
+                 <Hello001Button/>
              </RecoilRoot>
          </div>
      );
  };
  • useEffec を使ってみる
    010_useEffect.png
    atomの文字数をタイトルに表示するようにしてみました。
src/Hello001Button.tsx
+ import { FC, useEffect } from "react";
  import { useRecoilState } from "recoil";
  import { Hello001Atom } from "./Hello001Atom";

  export const Hello001Button:FC = () => {
      const [strAtom, setStrAtom] = useRecoilState(Hello001Atom);

      const onClickHandler = () => {
          setStrAtom(strAtom + ',a');
      }; 

+     useEffect(() => {
+         document.title = 'Hello001Button:' + strAtom.length.toString();
+     }, [strAtom]);

      return (
          <button onClick={onClickHandler}>ボタン</button>
      );
  };

おわりに

もし、もう一回やる場合は、初期状態に戻してもいいですし
Hello002.tsx を作って(内容は Hello001.tsx と同じ)
以下のように Hello001 の上に Hello002 を配置してもいいと思います。
(このようにすると繰り返してやってる感が出るかなと)

src/App.tsx
  import { useState } from 'react'
  import reactLogo from './assets/react.svg'
  import viteLogo from '/vite.svg'
  import './App.css'
  import { Hello001 } from './Hello001'
+ import { Hello002 } from './Hello002'

  function App() {
    const [count, setCount] = useState(0)

    return (
      <>
+       <Hello002/>
        <Hello001/>
        <div>
        以下略
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