Closed8

React初めまして学習

やじはむやじはむ

なんかモダンそうなReactとNext.jsを使って個人ブログサイトを作成するために一旦Reactチュートリアルとやってみることにした
https://ja.reactjs.org/tutorial/tutorial.html#function-components

最初普通のURLに飛ぶと英語で出てきてGoogle翻訳使って無理やり日本語にしていたけど分かりづら過ぎて結局英語のまま進めてたら多分60%くらいしか理解できなかった("ja"をURLに入れると日本語版出てくるらしい)
ので、明日チュートリアルの内容をもっかい復習してみることにする
最終的には自分の頭の中だけでかけるようになりたい

やじはむやじはむ

チュートリアル解説の記事も読んでみたりしてみたが、やっぱりよく分からないのでそのまま飲み込むことにする
大切なのは、恐らく"状態管理"と"コンポーネントの設計"なのかな?

次はローカルで試してみたい。↓を進めていこうと思う
https://ja.reactjs.org/docs/hello-world.html

やじはむやじはむ

重要なことメモ

コマンド

  • プロジェクトの作成
npx create-react-app react_app(プロジェクトの名前)
  • ブラウザ上で動作確認
npm start または yarn start
  • ビルド
npm build
  • テスト実行
npm test

コード

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
  • JSXを使うときに必要なBabelの使いどころ(Babelを使用してコンパイルされる)
<script type="text/babel">~</script>
  • 条件の記述
    • { 真偽値 && ...JSXの記述... } 真偽値がtrueの時JSXの部分が有効になる
<script type="text/babel">
     let dom = document.querySelector("#root");

     let message = function(msg, size, color) {
         const msgStyle = {
             fontSize: size,
             color: color
         };
         return <p style={ msgStyle }>{ msg }</p>
     }

     let msg1Flg = true;
     let msg2Flg = false;

     let el = (
         <div>
            { msg1Flg && message("message1", 30, "red") }
            { msg2Flg && message("message2", 20, "blue") }
         </div>
     );
     ReactDOM.render(el, dom);
</script>
  • mapの使い方
{mapData.map((value) => (
         <tr>
              <td>{ value.name }</td>
              <td>{ value.mail }</td>
              <td>{ value.age }</td>
         </tr>
))}
  • イベントの定義
<script type="text/babel">
    let dom = document.querySelector("#root");

    let message = "お名前を入力してください";
    let inputtedName = "";

    let change = (e) => {
      inputtedName = e.target.value;
      message = "こんにちは、" + inputtedName + "さん!";
   }

   let action = (e) => {
      let el = (
         <div>
              <p>{ message }</p>
              <div>
                 <input type="text" id="input" onChange={ change } />
                 <button onClick={ action }>Click</button>
              </div>
         </div>
     );
     ReactDOM.render(el, dom);
 };

 action();
</script>
やじはむやじはむ

重要なことメモ

コンポーネント

  • コンポーネントの表示
    • function コンポーネント名()props{}でコンポーネントを定義する
    • 実際にそのコンポーネントを使うときは<コンポーネント名 />で使う
    • コンポーネント名は必ず大文字
<script type="text/babel">
  let dom = document.querySelector("#root");

  const msg = {
     fontSize: "20px",
     fontWeight: "bold",
     padding: "10px",
     color: "red",
     backgroundColor: "darkblue"
 };

 function Welcome(props) {
     return <p style={ msg }>Hello React!</p>;
 }

 let el = (
    <div>
         <Welcome />
    </div>
  );
  ReactDOM.render(el, dom);
</script>
  • 属性の利用
function Welcome(props) {
   return <p style={ props.style }>Hello { props.name }!</p>;
}
let el = (
    <div>
        <Welcome name="Taro" style={ msg1 } />
        <Welcome name="Hanako" style={ msg2 } />
    </div>
);

クラスコンポーネント

  • 普通のクラス定義
class クラス名 {
    constructor(props) {  // オブジェクトが作成されたときに最初に呼び出されるメソッド
        super(props);  // これ必須
	// 初期化処理;
    }
    プロパティ;
    メソッド (引数) {};  // functionの記述いらない
}
  • 継承あり
class クラス名 extends 継承するクラス {
    プロパティ;
    メソッド;
}
  • デフォルトでReact.Componentというクラスがあるため基本これを継承する
class MyClass extends React.Compenent {
    render() {  // React.Componentを継承するときは必ずrender関数を用意する
        return ...JSX...;
    }
}
  • 属性をクラスに渡す
class Rect extends React.Component {
            x = 0;
            y = 0;
            width = 0;
            height = 0;
            color = "white";
            style = {};

            constructor(props) {
                super(props);
                this.x = props.x;
                this.y = props.y;
                this.width = props.width;
                this.height = props.height;
                this.color = props.color;
                this.style = {
                    backgroundColor: this.color,
                    position: "absolute",
                    left: this.x + "px",
                    top: this.y + "px",
                    width: this.width + "px",
                    height: this.height + "px"
                }
            }

            render() {
                return <div style={ this.style }></div>;
            }
        }

        let el = (
            <div>
                <Rect x="100" y="100" width="100" height="100" color="cyan" />
                <Rect x="150" y="150" width="100" height="100" color="magenta" />
            </div>
        );
  • いろんな変数
    • プロパティ→クラスに値を持たせるための変数のこと。コンポーネントに限らず、クラス全体で使用できる。
    • props→コンポーネントの属性をまとめて保管するためのもの。基本的に「read only」。
    • ステート→コンポーネントの状態を表す値を保管するもの。

ステート

  • 定義
constructor(props){
    super(props);
    this.state = {
      msg: "Hello State!"
    };
  }

  render() {
    return <div>
      <h1>React</h1>
      <p style={this.msgStyle}>{this.state.msg}</p>
      <p style={this.msgStyle}>{this.props.msg}</p>
    </div>
  }
やじはむやじはむ

重要なことメモ

ステート

  • ステートの更新
    this.setState((state) => ({}))現在のステートの値を利用して新たな値に更新する場合に使用
constructor(props) {
     super(props);
     this.state = {
         msg: "Hello State!"
     };

     setInterval(() => {
         this.setState((state) => ({
             msg: state.msg + "!"
         }));
     }, 500);
}

バインド

  • コンポーネントに関数を渡すとき、バインドが必要
constructor(props) {
        super(props);
        this.state = {
            counter: 0,
            msg: "count start!",
            flg: true
        };

        this.doAction = this.doAction.bind(this);
    }

    doAction() {
        this.setState((state) => ({
            counter: state.counter + 1,
            msg: state.counter,
            flg: !state.flg
        }));
    }

    render() {
        return <div>
            <h1>React</h1>
            {this.state.flg ?
                <p style={ this.msgStyle1 }>count: { this.state.msg }</p>
                :
                <p style={ this.msgStyle2 }>{ this.state.msg }です。</p>
            }
            <button onClick={ this.doAction }>Click</button>
        </div>;
    }

なんでbindが必要なのか調べたが、thisが何を指すかがわからなくなってしまうからということしかよくわからなかった
https://numb86-tech.hatenablog.com/entry/2019/12/04/110013
↓読んだら分かりやすかった!!「thisが指すものがは結局よくわからない」が正しいみたい
未定義状態になっているため、bindが必要
constructor内でthisをbindすることで、関数が実行されるときに使われるthisは、constructorで参照されているthisと同じになる。つまり、ここのthisはクラスのインスタンスになる
https://zenn.dev/souhal/articles/905ea271d4b070

プロパティとステートの連携

  • プロパティに生データを保管し、それをステートに渡して表示を変えたりすることができる
    ↓だったら、実際のデータはプロパティdata[]に保管し、stateでlistにはdata[]が該当するよと何の変数を持つかをより抽象的に定義できる
class App extends Component {
  data = []

  msgStyle = {
      fontSize: "24px",
      color: "red",
      margin: "20px 0px",
      padding: "5px",
  }

  area = {
      width: "500px",
      height: "500px",
      border: "1px solid green"
  }

  constructor(props) {
      super(props);
      this.state = {
          list: this.data
      };

      this.doAction = this.doAction.bind(this);
  }

  doAction(e) {
      let x = e.pageX;
      let y = e.pageY;
      this.data.push({ x: x, y: y });
      this.setState({
          list: this.data
      });
  }

  draw(d) {
      let s = {
          position: "absolute",
          left: (d.x - 25) + "px",
          top: (d.y - 25) + "px",
          width: "50px",
          height: "50px",
          backgroundColor: "blue"
      };
      return <div style={ s }></div>
  }

  render() {
      return <div>
          <h1>React</h1>
          <h2 style={ this.msgStyle }>show rect</h2>
          <div style={ this.area } onClick={ this.doAction }>
              { this.data.map((value) => this.draw(value)) }
          </div>
      </div>;
  }
}
このスクラップは2022/12/10にクローズされました