4
1

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.

React.js を使ってみた

Last updated at Posted at 2023-07-01

はじめに

HTML+JavaScript でアプリを作るのに、Vue.js を愛用してきました。
最近は React.js が流行のようです。使ってみることにしました。

React.js とは

React は、ユーザインタフェース構築のためのJavaScriptライブラリである。シングルページアプリケーションやモバイルアプリケーションの開発におけるベースとして使用することができる。

React - Wikipedia

React.js を使ってみた

・React.js 18

インストールする

React.js のアプリを作るには、Node.js を使ってローカルな開発環境を構築するのが一般的なようです。

React 開発環境構築 - Qiita

今回はあくまでも HTML ファイル一つで、ブラウザだけで動く React.js アプリを作ってみたいと思います。

npmを使わずにReactの開発環境を構築する方法(オフィシャルサイトからダウンロード) | Syntax Error.
npmを使わずにReactの開発環境を構築する方法(CDNで配信されているReactとbabel-coreを利用) | Syntax Error.

HTML ファイルに以下を追記します。

  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

React.js を使うコードは、以下の <script> タグに記載します。

  <script type="text/babel">

レンダリングする

HTML ファイルにはアプリの起点になるタグを用意します。

  <body>
    <div id="root"></div>
  </body>

起点になるタグに対して JavaScript のコードで HTML タグをレンダリングします。

    const root = ReactDOM.createRoot(document.querySelector('#root'));
    root.render(
      <p>Hello, React.js!</p>
    );

参考 React入門チュートリアル (2) JSX | Hypertext Candy

ネットの入門記事を見ていると以下の書き方を多く見かけました。最新の React.js では前述の書き方がいいようです。

    const root document.querySelector('#root');
    ReactDOM.render((
      ........
    ), root);

参考 React 18ではReactDOM.renderではなくcreateRootを使う | iwb.jp

render() に記述する HTML タグでは、JavaScript のコードの変数や式を埋込できます。

    const name = "React.js!";

    const root = ReactDOM.createRoot(document.querySelector('#root'));
    root.render(
      <p>Hello, { name }</p>
    );

配列のデータを一覧表示することも可能です。

    const members = [
      { name: "John", instrument: "guitar" },
      { name: "Paul", instrument: "bass" },
      { name: "George", instrument: "guitar" },
      { name: "Ringo", instrument: "drums" }
    ];

    const root = ReactDOM.createRoot(document.querySelector('#root'));
    root.render(
      <div>
        { 
          members.map((member, index) =>
            <p key={ index }> { member.name } plays { member.instrument }.</p>
          )
        }
      </div>
    );

個人的には Vue.js の <v-for> の方が分かりやすく思いますね。

コンポーネントを作成する

React.js は、独自のコンポーネントを作って利用することができます。

    class Element extends React.Component {
      render() {
        return <p>Hello, { this.props.name }</p>;
      }
    }

    const root = ReactDOM.createRoot(document.querySelector('#root'));
    root.render(
      <Element name="React.js" />
    );

独自タグを作れると言ってよさそうです。↑
呼出元から値を渡してコンポーネントで受取して使用できます。「属性」と言うそうです。

最近の React.js では、クラスを使うのでなく関数で定義するのがいいそうです。↓
「属性」は引数で受取ります。

    const Element = function(props) {
      return <p>Hello, { props.name }</p>;
    };

    const root = ReactDOM.createRoot(document.querySelector('#root'));
    root.render(
      <Element name="React.js" />
    );

「属性」を受取するところを書換えます。↓

    const Element = function({ name }) {
      return <p>Hello, { name }</p>;
    };

参考 【React】コンポーネントの基本と使い方を初心者向けに解説! | ちょいっぽ

コンポーネントに状態を加える

コンポーネントは、呼出元から値を受取って使うだけでなく、内部で値を保持して使用します。

カウントアップするボタンのコンポーネントを作ってみます。↓

    const CountButton = function() {
      let count = 0;

      function addCount() {
        count += 1;
      };

      return (
        <button onClick={ addCount }>Count: { count }</button>
      );
    };

    const root = ReactDOM.createRoot(document.querySelector('#root'));
    root.render(
      <CountButton />
    );

count の値は変わるのですが、{ count } で表示される値は変わりません。再描画されないのです。
そこで React.js は、値を変えると同時に再描画させる仕組を用意しています。「状態」を管理すると言います。

    const CountButton = function() {
      const [ count, setCount ] = React.useState(0);

      function addCount() {
        setCount(count + 1);
      };

      以下略

useState で変数と、変数を更新するメソッドを用意しておきます。useState の引数は、変数の初期値です。

参考 React入門チュートリアル (3) 属性と状態 | Hypertext Candy

用意する変数が配列のときは、どうでしょう。↓

    const Element = function() {
      const [ items, setItems ] = React.useState([
        { id: 1, name: "Item1", amount: 1 },
        { id: 2, name: "Item2", amount: 1 },
        { id: 3, name: "Item3", amount: 1 },
      ]);

      function addItem(item) {
        items.push(item)  
      }

      function updateItem(index, item) {
        items[index] = { ...item };
      }

      function removeItem(index) {
        items.splice(index, 1);
      }

      以下略

以前にあるように、これでは再描画されません。
useState で用意したメソッドを使います。↓

      function addItem(item) {
        setItems([ ...items, item ]);
      }

      function updateItem(index, item) {
        setItems(items.map((item, n) => {
          if (n == index) items[index] = { ...item }; return item;
        }));
      }

      function removeItem(index) {
        setItems(items.filter((item, n) => (n != index)));
      }

参考 useStateで配列要素を追加・削除・変更する方法 - Qiita

イベントをハンドリングする

前述のコードで既に書いていますが、HTML のタグが受取ったイベントを処理することができます。


    const Element = function() {
      const [ name, setName ] = React.useState("React.js");

      function handleChange(e) {
        setName(e.target.value);
      }

      return (
        <div>
          <p>Hello, { name }</p>
          <input value={ name } onChange={ handleChange } />
        </div>
      );
    };

参考 React入門チュートリアル (4) フォームとイベントハンドリング | Hypertext Candy

コンポーネント間で状態を共有する

ルートのコンポーネントで用意した変数を、子供や孫のコンポーネントで使用したいときは、どうしたらいいでしょうか。

useState で用意した変数とメソッドを、「属性」としてコンポーネントに渡せばいいようです。↓

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

      return (
        <div>
          <Parent count={ count } setCount={ setCount } />
        </div>
      );
    };

    const Parent = function({ count, setCount }) {
      function addCount() {
        setCount(count + 1);
      }

      return (
        <div>
          <p>Parent</p>
          <button onClick={ addCount }>{ count }</button>
          <Child count={ count } setCount={ setCount } />
        </div>
      );
    };

    const Child = function({ count, setCount }) {
      function addCount() {
        setCount(count + 1);
      }

      return (
        <div>
          <p>Child</p>
          <button onClick={ addCount }>{ count }</button>
          <GrandChild count={ count } setCount={ setCount } />
        </div>
      );   
    };

    const GrandChild = function({ count, setCount }) {
      function addCount() {
        setCount(count + 1);
      }

      return (
        <div>
          <p>GrandChild</p>
          <button onClick={ addCount }>{ count }</button>
        </div>
      );
    };

渡したい変数やメソッドが多くなったり、親子の階層が深くなると、引数で渡すのは面倒です。
そこで React.js は、グローバルな「状態」を保持できる仕組を用意しています。

    const CountContext = React.createContext();

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

      return (
        <div>
          <CountContext.Provider value={{ count, setCount }}>
            <Parent />
          </CountContext.Provider>
        </div>
      );
    };

    const Parent = function() {
      const { count, setCount } = React.useContext(CountContext);
   
      中略    

          <Child />
        </div>
      );
    };

    const Child = function() {
      const { count, setCount } = React.useContext(CountContext);

      中略    
          <GrandChild />
        </div>
      );
    };

    const GrandChild = function() {
      const { count, setCount } = React.useContext(CountContext);

      中略    
    };

useContext で用意したオブジェクトを使います。

参考 【React】useContextの使い方!初心者向けに分かりやすく解説! | ちょいっぽ

レンダリングのタイミングで実行する

レンダリングのタイミングで処理を実行したいことがあります。

    const App = function() {
      const [ visible, setVisible ] = React.useState(false);

      function toggleVisible() {
        setVisible(!visible);
      }

      return (
        <div>
          <button onClick={ toggleVisible }>表示を切替</button>
          <p>{ visible ? "true" : "false" }</p>
          <p>{ visible && <Child /> }</p>
        </div>
      );
    };

    const Child = function() {
      React.useEffect(function(){
        console.log("Hello, Child.");
      
        return(function(){
          console.log("Bye, Child.");
        });
      });

      return (
        <span>Child</span>
      )
    };

参考 【React】useEffectの使い方!初心者向けに分かりやすく解説! | ちょいっぽ

userState の使い所って何なのでしょう。

参考 【保存版】「そのuseEffectの使い方あってる?」と言われる前に

チュートリアル

ここまで基本が分かると、以下のチュートリアルは容易に理解できると思います。

チュートリアル:React の導入 – React

4
1
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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?