LoginSignup
0
0

More than 1 year has passed since last update.

Reactの講座で学んだ事をまとめてます!

Last updated at Posted at 2022-11-10

まずは、Javascriptを学ぼう!!

Javascriptの変数の定義の仕方:

var val1 = "var変数";
console.log(val1);
//=> var変数

val1 = "var変数を上書き"
console.log(val1)
//=> var変数を上書き

var val1 = "var変数を再宣言"
console.log(val1);
//=> var変数を再宣言

varの変数宣言では何でも出来てしまう

=>プロジェクトが大きくなってくると意図しない所で変数を再宣言,上書きしてしまう!!

そこで、、、

let , constという宣言が追加された
let: 上書きは出来るが再宣言出来ない
let val2 = "let変数";
console.log(val2)

val2 = "let変数を上書き";
console.log(val2)

let val2 = "let変数を再宣言"
//=>Identifier 'val2' has already been declared 
const: 上書き , 再宣言出来ない
const val3 = "const変数"
console.log(val3)
//=>const変数 

val3 = "const変数を上書き";
//=>"val3" is read-only

const val3 = "const変数を再宣言"
//=> Identifier 'val3' has already been declared

Javascriptのオブジェクトや配列は値を変えれる!!

オブジェクト:

const val4 = {
  name: "じゃけぇ",
  age: 28,
};

console.log(val4);
//=> name: "じゃけぇ", age: 28}

//nameの中身を書き換える
val4.name = "jak";

//新しいプロパティを追加する
val4.address = "Hiroshima";
console.log(val4)
//=> name: "jak", age: 28, address: "Hiroshima"}

配列:

const val5 = ['dog', 'cat'];
console.log(val5)
//=> ["dog", "cat"]

//配列の中身を変える
val5[0] = "bird"
console.log(val5)
//=> ["bird", "cat"]

//配列を追加する
val5.push("monkey")
console.log(val5)
//=> ["bird", "cat", "monkey"]

Reactでは基本constを使い、処理の中で変更が必要な場合、letを使う!!

テンプレート文字列

簡単に言うと、文字列の中にJavascriptの変数が便利に埋め込めるようになった。

「私の名前はじゃけぇです。年齢は28歳です」と表示させたい時、、、
従来の方法:

const name = "じゃけぇ";
const age = 28;

const message1 = "私の名前は" + name + "です。年齢は" + age + "です。";
console.log(message1);

上記の方法だと、コードが長くなって読みずらくなってしまう。

=> テンプレート文字列を用いる
const name = "じゃけぇ";
const age = 28;

//文字列をバッククオテ―ション(``)で囲む
const message2 = `私の名前は${name}です。年齢は${age}です。`;
console.log(message2);

アロー関数

従来の関数の書き方:
function func1(str) {
  return str;
}

console.log(func1("func1です"));
//=> func1です
const func1 = function (str) {
  return str;
};

console.log(func1("func1です。"));
//=> func1です。

アロー関数:

  • functionは書かずにそのまま引数を書く
  • => がアロー関数の由来
  • 処理の中で => がある。 = 関数を使っていると思って良い
const func2 = (str) => {
    return str;
};

console.log(func2("func2です。"));
//=> func2です。

引数を書いて、 「=>」を書いてその後{}で処理を書いていくという書き方

引数が2つの時、、、

const func3 = (num1, num2) => {
    return num1 + num2;
};

console.log(func3(10,20));
//=>30

分割代入

const myProfile = {
    name: "じゃけぇ"
    age: 28
};

const message1 = `名前は${myProfile.name}です。年齢は${myProfile.age}`;
console.log(message1);

//=> 名前はじゃけぇです。年齢は28 
myProfileという変数がもっと長かったり、もっと設定項目が多いとコードが読みずらくなる。
=> 分割代入を用いてコードを綺麗にする!
分割代入(const { name, age } = myProfile)で、
オブジェクトから指定のプロパティを抜き出して自由に使えるようになる。
const myProfile = {
  name: "じゃけぇ",
  age: 28
};

const { name, age } = myProfile;
const message2 = `名前は${name}です。年齢は${age}歳です。`;
console.log(message2);
//=> 名前はじゃけぇです。年齢は28歳です。
何と! 配列にも使える!

ちなみに、分割代入を使わない時は、、、

const myProfile = ["じゃけぇ", 28];
const message3 = 名前は${myProfile[0]}です年齢は${myProfile[1]}歳です`;
console.log(message3);
//=>名前はじゃけぇです。年齢は28歳です。 
分割代入を使うと、、、

配列の場合、オブジェクトのように名前が決まってないので順番に受け取る
myProfileの最初の要素がname , 次の要素がageに入る

const myProfile = ["じゃけぇ", 28];
const [name, age] = myProfile;
const message4 = `名前は${name}です。年齢は${age}歳です。`;
console.log(message4);
//=> 名前はじゃけぇです。年齢は28歳です。 

デフォルト値、引数など

const sayHello = (name) => console.log(`こんにちは${name}さん!`);
sayHello("じゃけぇ");
//=> こんにちはじゃけぇさん!

引数が渡されない時、、、

sayHello();
//=> こんにちはundefinedさん!
//値が入っていない初期状態undifinedと判定される

引数が渡されない時のデフォルトの値を設定したいとき
nameの後に = を付けて設定したい値を入れる

const sayHello = (name = "ゲスト") => console.log('こんにちは${name}さん!');
sayHello();
//=> こんにちはゲストさん

sayHello("じゃけぇ");
//=>こんにちはじゃけぇさん!

スプレッド構文

従来の配列の展開、、、

const arr1 = [1,2];
console.log(arr1);
//=> [1,2]

スプレッド構文で配列を展開すると、、、

const arr1 = [1, 2];
console.log(...arr1);
//  => 1 2

配列だったが実際の1,2という値になっている。
配列の中身を順場に処理して展開する

const arr1 = [1, 2];
const sumFunc = (num1, num2) => console.log(num1 + num2);
sumFunc(arr1[0], arr1[1]);
//=>3

スプレッド構文を使って引数を渡すと、、、

const sumFunc = (num1, num2) => console.log(num1 + num2);
const arr1 = [1, 2];
sumFunc(...arr1);
//=> 3

スプレッド構文で渡すと要素が順番に設定されるので、↑の行と同じ事をしている
イメージ: ... => 順番に処理する

展開の反対で1つにまとめる

配列をまとめて受け取るのに使える

const arr2 = [1,2,3,4,5,6];
const [num1, num2, ...arr3] = arr2;

console.log(num1);
//=>1

console.log(num2);
//=>2

console.log(arr3);
//=>[3, 4, 5]

配列のコピー、結合

const arr4 = [10, 20];
const arr5 = [30, 40];

//arr4の同じ要素を持つarr6という配列を作る
const arr6 = [...arr4];
console.log(arr6);
//=>[10, 20]

arr4とarr5を結合した新しい配列を作る

const arr4 = [10, 20];
const arr5 = [30, 40];
const arr7 = [...arr4, ...arr5];
console.log(arr7);
// => [10, 20, 30, 40]

...arr4 => arr4を展開してできた10,20
...arr5 => arr5を展開してできた30,40
よって、[10,20,30,40,50]という配列が作られる

コピーするだけなら下記のような書き方でも良いのでは、、、?
const arr4 = [10, 20];
const arr8 = arr4;

console.log(arr8);
//=> [10,20]

arr8[0] = 100;
console.log(arr4);
//=> [100,20]
元々,arr4 = [10 , 20]だったのが[100,20]になっている!:scream:
=>元の配列も変わってしまう
=> 不具合が発生する可能性がある!

配列をコピーしたいときはスプレッド構文を使う!

mapやfilterを使った配列の処理

for文を使った処理:

const nameArr = ["田中", "山田", "じゃけぇ"];
for (let index = 0; index < nameArr.length; index++) {
  console.log(nameArr[index]);
}

// =>田中
//   山田
//   じゃけぇ

mapを使った処理:

const nameArr = ["田中", "山田", "じゃけぇ"];

const nameArr2 = nameArr.map((name) => {
  return name;
});

console.log(nameArr2);
// =>["田中", "山田", "じゃけぇ"]

順場に入ってきた値をそのまま返している
for文と同じ結果になっている。
const nameArr = ["田中", "山田", "じゃけぇ"];
nameArr.map((name) => {
  console.log(name);
});

// => 田中
//    山田
//    じゃけぇ

map: 配列に対して使って、中で順番に要素が引数に設定され、それを関数内で処理させる
mapの使い方:
  • 単純に配列をループさせて何かを処理する
  • returnされた結果に基づいて新しい配列を作る
filter: ある条件に一致したものだけ返して新しい配列を作る
const numArr = [1, 2, 3, 4, 5];

//この配列から奇数を取り出して新しい配列を作りたい時
const newNumArr = numArr.filter((num) => {
  return num % 2 === 1;
});
console.log(newNumArr);
// =>[1, 3, 5]
mapで配列が何番目かを表示させたいとき、、、

1つ目の引数には配列の要素が入り、2つ目の引数には順番が0から入る

const nameArr = ["田中", "山田", "じゃけぇ"];
nameArr.map((name, index) => {
  console.log(`${index + 1}番目は${name}です`);
});

// =>  1番目は田中です
//     2番目は山田です
//     3番目はじゃけぇです
const nameArr = ["田中", "山田", "じゃけぇ"];
↑の要素の"じゃけぇ"以外に「さん」を付けて新しい配列を作りたいとき、、、
const nameArr = ["田中", "山田", "じゃけぇ"];
const newNameArr = nameArr.map((name) => {
  if (name === "じゃけぇ") {
    return name;
  } else {
    return `${name}さん`;
  }
});
console.log(newNameArr);
//=>["田中さん", "山田さん", "じゃけぇ"]
三項演算子

構文: ある条件? 条件がtrueの時 : 条件がfalseの時

const val1 = 1 > 0 ? "trueです" : "falseです";
console.log(val1);
//=> trueです
const num = 1300;

//toLocalString: 金額とかで,区切りに3桁表示してくれる。
console.log(num.toLocaleString());

//=>1,300
const num = "1300";
const formattedNum =
// typeof: その変数の型が何かを判定する
  typeof num === "number" ? num.toLocalString() : "数値を入力してください";

console.log(formattedNum);
// => 数値を入力してください
const checkSum = (num1, num2) => {
  return num1 + num2 > 100 ? "100を超えています!!" : "許容範囲内です";
};
console.log(checkSum(50, 40));
//=> 許容範囲内です
関数のreturn部分でも三項演算子を使ったりする
論理演算子の本当の意味を知ろう(&& ||)

一般的な使い方:

const flag1 = true;
const flag2 = false;

if (flag1 || flag2) {
  console.log("1か2はtrueになります");
}
// //=>1か2はtrueになります

if (flag1 && flag2) {
  console.log("1も2もtrueになります。");
}
//=> (何も表示されない)
実は || && は、「または」 , 「かつ」という意味ではない。

例: ||の場合

const num = null;
const fee = num || "金額未設定です";
console.log(fee);
//=>金額未設定です
const num = 100;
const fee = num || "金額未設定です";
console.log(fee);
//=> 100

何故、このような事が起きるのか?

|| は左側がfalseなら右側を返すという意味:flushed:

||の左側がtrueならそのまま左側を返す:flushed:

例: &&の場合

const num2 = 100;
const fee2 = num2 && "何か設定されました";
console.log(fee2);
//=> 何か設定されました
const num2 = null;
const fee2 = num2 && "何か設定されました";
console.log(fee2);
// => null

&& は左側がtrueなら右側を返す falseなら左側を返す:flushed:

Reactを学ぼう!!

一旦、大事なこと:
public/index.html

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

ReactなどのSPA開発では、index.html自体は一枚で
後は、Javascriptで要素を書き換えて画面の遷移を表現する

この記述はHTMLのどの部分にJavascriptを差し込んでいくかという目印

src/index.js


import { StrictMode } from "react";
import ReactDom from "react-dom";

import App from "./App";

//renderという処理で実際にJavascriptの内容を反映する
ReactDom.render(
  <StrictMode>
    
    //import APP from "./APP"より、APP.jsというファイルを読み込む
    <App />
  </StrictMode>,

  //rootというidを取得する
  document.getElementById("root")

);

APP.js

import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

index.jsで読み込まれて↓のような画面が表示される!
1.PNG

JSX記法について

index.js

import React from react

この記述は、Reactのコンポーネントを書いていくのに
必ず必要!!

import ReactDom from 'react-dom 

index.jsには、HTMLにコンポーネントを反映していく必要がある
それに必要なReactDomをimportする

Reactでは関数を使って画面の要素であるコンポーネントを表現する
const APP = () => {
    return null;
}
//これでnullという値を返すAPPという関数が出来た

この関数を画面に反映するためにReactDomの中にあるrenderという関数を使う
ReactDom.render(<レンダリングする関数名 /> , 反映する場所)

const APP = () => {
    return null;
}

ReactDom.render(<App /> , document.getElementById("root"))

実際にJSX記法を使って画面に要素を表示してみよう!!

ReactではJavascriptの中にHTMLを書いていく感じ


import React from "react";
import ReactDom from "react-dom"

const App = () => {
  return <h1>こんにちは</h1>
}

ReactDom.render(<APP />, document.getElementById("root"));

2.PNG

更に、JSX記法を使って要素を追加してみよう!!

要素が複数(returnのに内容が複数)の時は、
下記のようにreturnに()を用いる


import React from "react";
import ReactDom from "react-dom"

const App = () => {
  return (
    <h1>こんにちは</h1>
    <p>お元気ですか?</p>
  )
}

ReactDom.render(<APP />, document.getElementById("root"));

しかし、、、エラーが発生!!:scream:

3.PNG

JSX記法のルール: returnするHTMLの内容は1つのタグで囲む!!

今回は、divタグで囲む


import React from "react";
import ReactDom from "react-dom"

const App = () => {
  return (
    <div>
        <h1>こんにちは</h1>
        <p>お元気ですか?</p>
    </div>
  )
}

ReactDom.render(<APP />, document.getElementById("root"));

4.PNG

しかし、余分なdivがレンダリングされてしまう

=> エラーを回避するためならReact.Fragmentタグを使う!!


import React from "react";
import ReactDom from "react-dom"

const App = () => {
  return (
    <React.Fragment>
        <h1>こんにちは</h1>
        <p>お元気ですか?</p>
    </React.Fragment>
  )
}

ReactDom.render(<APP />, document.getElementById("root"));

コンポーネントの使い方を知ろう!!

Reactでは、画面の表示の部分を色々なファイルに分けてコンポーネントとして管理する

新しいファイル App.jsを作成する

import React from 'react';
import ReactDom from "react-dom";

const App = () => {
    return(
        <> //<React.Fragment>を省略する事が出来る
           <h1>こんにちは</h1>
           <p>お元気ですか?</p>
        </>
    );
};
    

このままでは、Appという関数はこのファイル上でしか使えない。
export default 関数名と記述する
関数を他でも使用出来るようにする

App.js

import React from 'react';
import ReactDom from "react-dom";

const App = () => {
    return(
        <> //<React.Fragment>を省略する事が出来る
           <h1>こんにちは</h1>
           <p>お元気ですか?</p>
        </>
    );
};

export default App;
    
exportが記述出来たのでindex.jsでAppとう関数を使おう!!
import React from "react";
import ReactDom from "react-dom";
import App from "./App";

ReactDom.render(<App />, document.getElementById("root"));

import 使いたい関数名 from "どのファイルからimportするのか"と記述する

他のファイルで画面のレンダリングの部分を作成し、
exportして、importする事でコンポーネントとして利用出来る

コンポーネントとして利用するファイルは.jsxにするとわかりやすい

Reactでのイベントやstyleの扱い方を知ろう!!

ボタンを押した時に~したいという機能を作りたい時、、、

1 buttonタグを記述する

App.js

import React from 'react';
import ReactDom from "react-dom";

const App = () => {
    return(
        <> //<React.Fragment>を省略する事が出来る
           <h1>こんにちは</h1>
           <p>お元気ですか?</p>
           <button onClick = {}>ボタン</button>
        </>
    );
};

export default App;
    

Reactの特徴:
HTMLのタグの中で使うイベント , styleの名称 => 単語の繋ぎ部分が大文字(キャメルケース)

 return(
        <> //<React.Fragment>を省略する事が出来る
           <h1>こんにちは</h1>
           <p>お元気ですか?</p>
           <button onClick = {}>ボタン</button>
        </>

jsxで返しているHTMLのタグを{}で囲むと
Javascriptとして認識される
=>{}で囲って、Javascriptの関数を書いていくイメージ

import React from 'react';
import ReactDom from "react-dom";

const App = () => {
  const onClickButton = () => alert();
    return(
        <> //<React.Fragment>を省略する事が出来る
           <h1>こんにちは</h1>
           <p>お元気ですか?</p>
            
            //{}の中に割り当てたい関数名を記述する => イベントを割り当てる事が可能
           <button onClick = {onClickButton}>ボタン</button>

        </>
    );
};

export default App; 

2-2.PNG

2-1.PNG

styleを割り当てる

return(
        <> 
           <h1 style = {{color: "red"}}>こんにちは</h1>
           <p>お元気ですか?</p>
           <button onClick = {onClickButton}>ボタン</button>

        </>
    );

3.PNG

style = {{}}:
外側の{}: Javascriptを書きますよ~という{}
内側の{}: Javascriptのオブジェクトの{}

変数を使ってstyleを割り当てる
import React from 'react';
import ReactDom from "react-dom";

const App = () => {
  const onClickButton = () => alert();
  const contentStyle = {
    color: 'blue';
    fontSize: '18px';
  };

    return(
        <> //<React.Fragment>を省略する事が出来る
          <h1 style = {{color: "red"}}>こんにちは</h1>
           <p style = {contentStyle}>お元気ですか?</p>
           <button onClick = {onClickButton}>ボタン</button>

        </>
    );
};

export default App; 

1.PNG

一度、オブジェクトの変数を定義して中にプロパティを書いて行く。
そして、それをstyleの中に反映させていく。

Propsを知ろう!!

props: コンポーネントに対して渡す引数のようなもの ,
ある程度、動的にコンポーネントを使えるように出来る。

例: コンポーネントとして画面を別ファイルに切り出しても
条件によっては、その振る舞いを変える必要がある
通常は黒文字 , エラーの時は赤文字

「元気です」という文字は女性用なので
ピンク色にしようとすると、、、
import React from "react";

const App = () => {
  const onClickButton = () => alert();
  const contentStyle = {
    color: "blue",
    fontSize: "18px"
  };

  const contentLeadyStyle = {
    color: "pink",
    fontSize: "18px"
  };

  return (
    <React.Fragment>
      <h1 style={{ color: "red" }}>こんにちは</h1>
      <p style={contentStyle}>お元気ですか?</p>
      <p style={contentLeadyStyle}>元気です!</p>
      <button onClick={onClickButton}>ボタン</button>
    </React.Fragment>
  );
};

export default App;

1.PNG

しかし、出てくるたびにstyleを分けるのはメンドクサイ!!
=> 文章をコンポーネント化して、色と文章をPropsとして受け取るようにすれば良い!

srcの配下にcomponentsというフォルダを作成する
色を付けた文字を表示するコンポーネント(ColorfulMessage.jsx)を作成する

src/components/ColorfulMessage.jsx

import React from 'react';

const ColorfulMessage = () => {
  const contentStyle = {
    color: 'blue';
    fontSize: '18px'; 
  }
  return (
    <p style = {contentStyle}>お元気ですか?</p>
  )
}

blueの文字色で指定された「お元気ですか?」というメッセージを返すコンポーネントを
作成できた。

App.jsxでimportしてColorfulMessageというコンポーネントを使う

App.jsx

import React from "react";
import ColofulMessage from './components/ColorfulMessage';

const App = () => {
    const onClickButton = ()  => alert();
    const contentLedyStyle = {
        color: 'pink';
        fontSize:'18px;
    };
    return (
        <>
           <h1 style = {{color: 'red'}}>こんにちは</h1>

           //タグの中にコンポーネントを入れる事で
           //ColofulMessageというコンポーネントを使える
           <ColofulMessage />

           <p style = {contentLedyStyle}>元気です!</p>
           <button onClick = {onClickButton}>ボタン</button>
        </>
    );
};

export default App;

このままだと、青文字で「お元気ですか」としか返さない
=>Propsで条件を渡して動的に変わるコンポーネントにする

Propsを渡す場合、
渡す方 , 渡される方 両方に修正を加える

渡す方: タグの中に渡したい名称を書いて行く
App.jsx(渡す方)

import React from "react";
import ColofulMessage from './components/ColorfulMessage';

const App = () => {
    const onClickButton = ()  => alert();
    const contentLedyStyle = {
        color: 'pink';
        fontSize:'18px;
    };
    return (
        <>
           <h1 style = {{color: 'red'}}>こんにちは</h1>

           //色を渡したいのでcolor , 文章を渡すのでmessageにした(任意で決めれる)
           <ColofulMessage color = "blue" message = "お元気ですか?"/>

           <p style = {contentLedyStyle}>元気です!</p>
           <button onClick = {onClickButton}>ボタン</button>
        </>
    );
};

export default App;

このようにして、
コンポーネントに対して適当な名前を付けて要素を渡していく事で
コンポーネントに対してPropsを渡せる

ColorfulMessage.jsx(Propsを渡される方)

import React from "react";

const ColorfulMessage = (props) => {
    const contentStyle = {
        color: "blue";
        fontSize: "18px";
    };
    
    return <p style = {contentStyle}>お元気ですか?</p>;
};

export default ColorfulMessage;

ここで、Propsの中身を確認すると、、、

const ColorfulMessage = (props) => {

    console.log(props);
    //=> {color: "blue", message: "お元気ですか?"}

    //colorというプロパティに「blue」という文字列
    //messageというプロパティに「お元気ですか?」という文字列が入っている

    const contentStyle = {
        color: "blue";
        fontSize: "18px";
    };

App.jsxで設定したPropsが渡ってきていると確認出来る
=>後は、コンポーネントの中で渡ってきた要素を使えば良い

import React from "react";

const ColorfulMessage = (props) => {
    const contentStyle = {
        color: props.color;
        fontSize: "18px;
    };
    
    //returnしているHTMLっぽい所でJavascriptを書く場合、{}で囲む
    return <p style = {contentStyle}>{props.message}</p>;
};

export default ColorfulMessage;

1.PNG

ピンク色の「元気です!」もPropsを使って記述すると、、、

App.jsx

import React from "react";
import ColofulMessage from './components/ColorfulMessage';

const App = () => {
    const onClickButton = ()  => alert();
    return (
        <>
           <h1 style = {{color: 'red'}}>こんにちは</h1>
           <ColofulMessage color = "blue" message = "お元気ですか?"/>
           <ColofulMessage color = "pink" message = "元気です!"/>
           <p style = {contentLedyStyle}>元気です!</p>
           <button onClick = {onClickButton}>ボタン</button>
        </>
    );
};

export default App;

初めは↓のようなスタイルがあってごちゃごちゃしていたが、
共通のコンポーネントを書くことでスッキリさせる

  const contentLedyStyle = {
        color: 'pink';
        fontSize:'18px;
    };

Propsのもう一つの渡し方、、、
ColorfulMessageというタグで囲って文章を設定する

App.jsx

 <ColofulMessage color="blue">お元気ですか?</ColofulMessage>
 <ColofulMessage color="pink">元気です!</ColofulMessage>

ColofulMessageというタグで囲った中身を使うようにする
=> childrenを用いる

ColorfulMessage.jsx

import React from "react"

const ColorfulMessage = (props) => {
    const contentStyle = {
       color: props.color,
       fontSize: "18px"
    };

    return <p style = {contentStyle}>{props.children}</p>;
}

export default ColorfulMessage;

コンポーネントのタグで囲った中身をそのまま渡すと
特別なchildrenという変数に入ってくる

Stateを知ろう!!

State: それぞれのコンポーネントが持っている状態
条件によって画面が自動的に変わる部分をStateとして
定義すれば良い。

Stateを使用する場合、useStateを使う必要がある

App.jsx

import React, { useState } from "react";
import ColofulMessage from "./components/ColorfulMessage";

const App = () => {
    const onClickButton = () => alert();
    useState();
    return(
        <>
           <h1 style = {{color: 'red'}}>こんにちは</h1>
           <ColofulMessage color="blue">お元気ですか?</ColofulMessage>
           <ColofulMessage color="pink">元気です!</ColofulMessage>
           <button onClick = {onClickButton}>ボタン</button>
        </>
    )
}
import React, { useState } from "react";

useStateは、Reactの中に入っている
=> 分割代入で中身からuseStateを取り出している

useStateから実際に使う変数を設定する
useStateの中から配列の分割代入で取り出していく

import React, { useState } from "react";
import ColofulMessage from "./components/ColorfulMessage";

const App = () => {
    const onClickButton = () => alert();

    //const[Stateとして使用する変数名 , そのStateを変更する為の関数名]
    //useState()の()に、初期値を設定することが出来る(今回は0)
    const [num, setNum] = useState(0);
    return(
        <>
           <h1 style = {{color: 'red'}}>こんにちは</h1>
           <ColofulMessage color="blue">お元気ですか?</ColofulMessage>
           <ColofulMessage color="pink">元気です!</ColofulMessage>
           <button onClick = {onClickButton}>ボタン</button>
        </>
    )
}

実際にnumという変数に0が格納されているのか
確認してみよう!!

import React, { useState } from "react";
import ColofulMessage from "./components/ColorfulMessage";

const App = () => {
    const onClickButton = () => alert();

    //const[Stateとして使用する変数名 , そのStateを変更する為の関数名]
    //useState()の()に、初期値を設定することが出来る(今回は0)
    const [num, setNum] = useState(0);
    return(
        <>
           <h1 style = {{color: 'red'}}>こんにちは</h1>
           <ColofulMessage color="blue">お元気ですか?</ColofulMessage>
           <ColofulMessage color="pink">元気です!</ColofulMessage>
           <button onClick = {onClickButton}>ボタン</button>
           <p>{num}</p>
        </>
    )
}

0.PNG

ボタンをクリックすると数字をカウントアップする機能を実装する

App.jsx

import React, { useState } from "react";
import ColofulMessage from "./components/ColorfulMessage";

const App = () => {
    const onClickCountUp = () => {
    
        //Stateを更新するには、2つ目に設定したsetNumという関数を使う
        //その中にnumをどのように更新したいか書く
        setNum(num + 1);
    }

    //const[Stateとして使用する変数名 , そのStateを変更する為の関数名]
    //useState()の()に、初期値を設定することが出来る(今回は0)
    const [num, setNum] = useState(0);
    return(
        <>
           <h1 style = {{color: 'red'}}>こんにちは</h1>
           <ColofulMessage color="blue">お元気ですか?</ColofulMessage>
           <ColofulMessage color="pink">元気です!</ColofulMessage>
           <button onClick = {onClickCountUp}>カウントアップ!</button>
           <p>{num}</p>
        </>
    )
}

0.PNG

再レンダリング , useEffect

まずは、顔文字を表示させる

App.jsx

import React , { userState } from "react";
import ColorfulMessage from "./components/ColorfulMessage";

const App = () => {
   const onClickCountUp = () => {
       setNum(num + 1);
   };
   const [num, setNum] = useState(0);
   return (
    <>
      <h1 style = {{ color: "red" }}>こんにちは!</h1>
      <ColorfulMessage color = "blue">お元気ですか?</ColorfulMessage>
      <ColorfulMessage color = "pink">元気です!</ColorfulMessage>
      <p>{num}</p>
      <p>!(^^)!</p>
   );
};

export default App;

ボタンを押すと顔文字を表示/非表示させる機能を実装する

import React , { userState } from "react";
import ColorfulMessage from "./components/ColorfulMessage";

const App = () => {
   const onClickCountUp = () => {
       setNum(num + 1);
   };
   const [num, setNum] = useState(0);
   return (
    <>
      <h1 style = {{ color: "red" }}>こんにちは!</h1>
      <ColorfulMessage color = "blue">お元気ですか?</ColorfulMessage>
      <ColorfulMessage color = "pink">元気です!</ColorfulMessage>
      <br />

      //ボタンを作成する
      <button>on/off</button>

      <p>{num}</p>
      <p>!(^^)!</p>
   );
};

export default App;

表示/非表示という状態を持たせる
=> 状態を定義する
=> Stateを定義する

import React , { userState } from "react";
import ColorfulMessage from "./components/ColorfulMessage";

const App = () => {
    const [num, setNum] = useState(0);
    
   //表示/非表示を扱うStateを定義する , 初期値をtrueにする
   //faceshowFlagを更新する為の関数がsetfaceShowFlag

   const [faceShowFlag , setFaceShowFlag] = useState(true)

   const onClickCountUp = () => {
       setNum(num + 1);
   };
  
   return (
    <>
      <h1 style = {{ color: "red" }}>こんにちは!</h1>
      <ColorfulMessage color = "blue">お元気ですか?</ColorfulMessage>
      <ColorfulMessage color = "pink">元気です!</ColorfulMessage>
      <br />
      <button>on/off</button>

      <p>{num}</p>
      <p>!(^^)!</p>
   );
};

export default App;

faceShowFlagがtrueの時だけ
顔文字部分がレンダリングされるようにする
=> &&: 左側がtrueの時に右側を返す

import React , { userState } from "react";
import ColorfulMessage from "./components/ColorfulMessage";

const App = () => {
    const [num, setNum] = useState(0);
    const [faceShowFlag , setFaceShowFlag] = useState(true)
    const onClickCountUp = () => {
       setNum(num + 1);
   };
  
   return (
    <>
      <h1 style = {{ color: "red" }}>こんにちは!</h1>
      <ColorfulMessage color = "blue">お元気ですか?</ColorfulMessage>
      <ColorfulMessage color = "pink">元気です!</ColorfulMessage>
      <br />
      <button>on/off</button>
      <p>{num}</p>

      {faceShowFlag && <p>!(^^)!</p>}

   );
};

export default App;

on/offボタンが押された時に、faceShowFlagのtrue/falseを切り替える

import React , { userState } from "react";
import ColorfulMessage from "./components/ColorfulMessage";

const App = () => {
    const [num, setNum] = useState(0);
    const [faceShowFlag , setFaceShowFlag] = useState(true)
    const onClickCountUp = () => {
       setNum(num + 1);
   };

   //この中で、setFaceShowFlagを切り替える
  // useStateで定義した関数を呼び出す
  // true => false , false => trueにする
  // => 現在のフラグ(faceShowFlag)の値の逆(!を付ければ良い)

   const onClickSwitchShowFlag = () => {
       setFaceShowFlag(!faceShowFlag);
   }
  
   return (
    <>
      <h1 style = {{ color: "red" }}>こんにちは!</h1>
      <ColorfulMessage color = "blue">お元気ですか?</ColorfulMessage>
      <ColorfulMessage color = "pink">元気です!</ColorfulMessage>
      <br />

      //onClickに定義したonClickSwitchShowFlagという関数を割り当てる
      <button onClick = {onClickSwitchShowFlag} >on/off</button>

      <p>{num}</p>

      {faceShowFlag && <p>!(^^)!</p>}

   );
};

export default App;

何故、再読み込みしてないのにnumが+1されたり、顔文字が表示されるのか?

=> Reactのコンポーネントが再レンダリングされているから。

ステイトの更新があった時に、Reactがそれを検知してコンポーネントを上から読み込み
h1 style = ~の表示が変わる

import React, { useEffect, useState } from "react";
import ColorfulMessage from "./components/ColorfulMesssage";

const App = () => {
 
  //ボタンを押すたびに表示される => ボタンを押すたびに一番上から読み込まれている
  console.log("最初");
  // const onClickButton = () => alert();
  const onClickCountUp = () => {
    setNum(num + 1);
  };

画面を再読み込みしてコンソールを見てみると、、、
453.PNG

一番、最初にconsole.log("最初")が通過されているのがわかる

ステイト変更時はどうなるかボタンを押して確認してみると、、、
ボタン(ステイト)を押すたびに読み込まれている.PNG

ステイトを変更すると , ボタンを押した数だけ表示される
=>setFaceShowFlagという関数でステイトが変更された時、
また、const App = () という関数コンポーネントが頭から読み込まれている

import React from "react";

const ColorfullMessge = (props) => {
  console.log("カラフル");
  const { color, children } = props;
  const contentStyle = {
    color: color,
    fontSize: "18px"
  };
  return <p style={contentStyle}>{children}</p>;
};

export default ColorfullMessge;

「カウントアップ」ボタンを押してStateを変更すると、、、

1.PNG

import React , { userState } from "react";
import ColorfulMessage from "./components/ColorfulMessage";

const App = () => {
    
    //ここが表示される
    console.log("最初");

    const [num, setNum] = useState(0);
    const [faceShowFlag , setFaceShowFlag] = useState(true)
    const onClickCountUp = () => {
       setNum(num + 1);
   };


   const onClickSwitchShowFlag = () => {
       setFaceShowFlag(!faceShowFlag);
   }
  
   return (
    <>
      <h1 style = {{ color: "red" }}>こんにちは!</h1>
        
       //ColofulMessageが2回読み込まれる
      <ColorfulMessage color = "blue">お元気ですか?</ColorfulMessage>
      <ColorfulMessage color = "pink">元気です!</ColorfulMessage>

      <br />
      <button onClick = {onClickSwitchShowFlag} >on/off</button>

      <p>{num}</p>

      {faceShowFlag && <p>!(^^)!</p>}

   );
};

export default App;
<ColorfulMessage color = "blue">お元気ですか?</ColorfulMessage>
<ColorfulMessage color = "pink">元気です!</ColorfulMessage>
import React from "react";

const ColorfullMessge = (props) => {

  //ここが表示される
  console.log("カラフル");

  const { color, children } = props;
  const contentStyle = {
    color: color,
    fontSize: "18px"
  };
  return <p style={contentStyle}>{children}</p>;
};

export default ColorfullMessge;

親のコンポーネントは、自分のStateが更新されたので
「最初」と表示される

親のコンポーネントが再レンダリングされ、それに追従して
「カラフル」と2回表示される

1.PNG

再レンダリングの仕組みを知らないと思わぬバグを引き起こす!?

カウントアップしていって、3の倍数の時に顔文字を表示する機能を実装する

numが3の倍数の時に、faceShowFlagをtrueにする


const App = () => {
  console.log("最初");
  const onClickCountUp = () => {
    setNum(num + 1);
  };
  const [num, setNum] = useState(0);
  const [faceshowFrag, setFaceShowFlag] = useState(false);

  const onClickSwitchShowFlag = () => {
    setFaceShowFlag(!faceshowFrag);
  };

if (num % 3 === 0) {
    setFaceShowFlag(true);
  } else {
    setFaceShowFlag(false);
  }

しかし、このような記述だと下記のようなエラーが出る!!
error.PNG

コンポーネント内で物凄い数の再レンダリングが起きている事によるエラー

原因:

//numに0という初期値が与えられる
const [num, setNum] = useState(0)
//num % 3 == 0より、

if (num % 3 === 0) {

    //こちらの処理が通り、ステイトが変更される
    setFaceShowFlag(true);

  } else {
    setFaceShowFlag(false);
}

ステイトが変更された事によって、
またコンポーネントが頭から読み込まれる

const App = () => {

このように、何度もステイトが変更されてAppがずっとループする事でエラーが起きている
=> Too many re-renders. ~というエラーが起きたら、ステイトの変更周りを注意しよう!!

解決策:
既に、setFaceShowFlagがtrueの時に、このフラグをtrueにする関数を呼ばないようにする
falseの時に、falseにする関数を呼ばないようにする

改善したコード:

if (num % 3 == 0) {
    faceshowFrag || setFaceShowFlag(true);
  } else {
    faceshowFrag && setFaceShowFlag(false);
  }

faceShowFlag || setFaceShowFlag(true);
setFaceShowFlag(true)がtrueの時にsetFaceShowFlagという関数を呼ばないようにする(falseの時に呼ぶ)
=> || : 左がfalseの時に右側の処理をやってくれる

faceShowFlag && setFaceShowFlag(false)
faceShowFlagがtrueの時にfalseにしたい
&&:左側がtrueなら右側の処理をする

しかし、on/offボタンが動かなくなってしまった!!

原因:

<button onClick={onClickSwitchShowFlag}>on/off</button>

この部分より、on/offボタンをクリックするとonClickSwitchShowFlagが呼ばれる
setFaceShowFlag(!faceshowFrag);が呼ばれて現在のfaceshowFragが反転する

ステイトが更新されたので頭から読み込まれる
if (num % 3 == 0)が読み込まれるがnumの値が変わってないので

if (num % 3 == 0) {
    //また、この部分を通る
    faceshowFrag || setFaceShowFlag(true);
  } else {
    faceshowFrag && setFaceShowFlag(false);
  }

フラグをfalseにしてもtrueにまた、更新されてしまう
結果として、on/offが効かない

扱う変数が増えたり、ステイトの数が増えると
それぞれの処理が邪魔しあって上手く動かなかったりする
=> 関心の分離をする

この部分をnumの値だけ関心を持つようにする!!

if (num % 3 == 0) {
    faceshowFrag || setFaceShowFlag(true);
  } else {
    faceshowFrag && setFaceShowFlag(false);
  }

関心の分離には、useEffectを用いる!

使い方:


const onClickCountUp = () => {
    setNum(num + 1);
};

const onClickSwitchShowFlag = () => {
    setFaceShowFlag(!faceShowFlag);
};

useEffect(()) => {
   console.log("useEffect");
});

if (num % 3 === 0 ){
    faceShowFlag || setFaceShowFlag(true);
}else{
    faceShowFlag && setFaceShowFlag(false);
}

1.PNG

useEffectに空の配列[]を設定する事で
最初は、useEffect!表示されるがステイトを更新すると
最初という文字しか表示されない
=> useEffectの中を通っていない
=> 空の配列を渡す事で最初の1回だけ通したい処理を書くことが出来る

例: 画面を表示するのにデータを取って来る事etc...


const onClickCountUp = () => {
    setNum(num + 1);
};

const onClickSwitchShowFlag = () => {
    setFaceShowFlag(!faceShowFlag);
};

useEffect(()) => {
   console.log("useEffect");
});

if (num % 3 === 0 ){
    faceShowFlag || setFaceShowFlag(true);
}else{
    faceShowFlag && setFaceShowFlag(false);
}

[]の中に変数を入れると
その変数が変化した時だけ通すように設定出来る!!

useEffect(() => {
    if (num % 3 == 0) {
      faceshowFrag || setFaceShowFlag(true);
    } else {
      faceshowFrag && setFaceShowFlag(false);
    }
    console.log("userEffect!!");
  }, [num]);

おまけ: default export と export

defaultとではない、もう一つのexportの仕方:

import React from "react";

//通常のexportの仕方(関数コンポーネントの定義の前にexportを付ける)
export const ColorfullMessge = (props) => {
  const { color, children } = props;
  const contentStyle = {
    color: color,
    fontSize: "18px"
  };
  return <p style={contentStyle}>{children}</p>;
};

//defaultのexportの仕方
export default ColorfullMessge;

しかし、エラーが発生した
error.PNG

通常のexportでは、importして使用する場合、分割代入をする

App.jsx


import React, { useEffect, useState } from "react";

//通常のexportのimport
import from {ColorfulMessage} from "./components/ColorfulMesssage";

//defaultのexportでのimport
//import ColorfulMessage from "./components/ColorfulMesssage";

Reactのコンポーネントでは、基本通常のexportを使えば良い!!

App.jsxでコンポーネントの名前を間違えたとき、、、

defaultのexportの時、、、

App.jsx


import React, { useEffect, useState } from "react";

//コンポーネントの名前を間違えても(本来は、ColorfulMessage)
import ColorfulMessag from "./components/ColorfulMesssage";

//この部分のタグも同じColorfulMessagにすれば、そのままプロジェクトが進んでしまう
<ColorfulMessag color="blue">お元気ですか</ColorfulMessag>
<ColorfulMessag color="pink">元気ですか</ColorfulMessag>


export default App;

1.PNG

通常のexportの時、
キャプチャ.PNG

エラーを出してくれる!!

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