LoginSignup
0
3

More than 3 years have passed since last update.

React 覚え書き

Last updated at Posted at 2021-04-18

プロジェクト作成

npx create-react-app react-sample
cd react-sample
npm start または yarn start

コメント

  • jsxの中では、{/* コメント */} を使う。
  • タグの中は、/* */ // も使える

クラスコンポーネント

src/App.js
import React, { Component } from "react";

class App extends Component {
  render() {
    return <p>Hello world {this.props.name}!</p>;
  }
}
export default App;

関数コンポーネント

  • シンプルだが、State、ライフサイクルメソッドが使えない
  • Hookを使うことにより、上記問題は解決する
import React from "react";

const App = (props) => {
  return <p>Hello world {props.name}!</p>;
};
export default App;

props

  • <App name="ichiro"></App> の場合 {this.props.name} = ichiro
  • <App><p>こんにちは</p></App> の場合 {this.props.children} = <p>こんにちは</p>

繰り返し

import React from "react";

const App = () => {
  const users = [{ name: "yamada" }, { name: "suziki" }, { name: "saito" }];

  return (
    <dl>
      {users.map((user, index) => (
        <ul key={index}>{user.name}</ul>
      ))}
    </dl>
  );
};
export default App;

条件分岐

// 条件演算子
{ this.props.isNew ? <NewIcon /> : null }
// &&演算子
{ this.props.isNew && <NewIcon /> }
// 即時関数
{(() => {
  if (this.props.isNew) {
    return <NewIcon />
  }
})}

stateを使ったフォーム

  • constructor()の中で、stateの初期化を行う。
  • this.setState()でstateの更新を行う。
import React, { Component } from "react";

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: "",
      prefecture: "",
      career: "",
      skill: [""],
      memo: "",
    };
    this.handleChange = this.handleChange.bind(this);
    this.handleChangeMulti = this.handleChangeMulti.bind(this);
    this.file = React.createRef(); // fileを参照できるようにする(Uncontrolled Component)
    this.show = this.show.bind(this);
  }

  handleChange(e) {
    this.setState({
      [e.target.name]: e.target.value,
    });
  }

  handleChangeMulti(e) {
    const fs = this.state.skill;
    if (e.target.checked) {
      fs.push(e.target.value);
    } else {
      fs.splice(fs.indexOf(e.target.value), 1);
    }
    this.setState({
      [e.target.name]: fs,
    });
  }

  show() {
    console.log(`${this.state.name}`);
    console.log(`${this.state.prefecture}`);
    console.log(`${this.state.career}`);
    console.log(`${this.state.skill}`);
    console.log(`${this.state.memo}`);

    const f = this.file.current.files[0];
    if (f) {
      console.log(`${f.name} ${f.type}  ${f.size}`);
    }
  }

  render() {
    return (
      <form>
        <label htmlFor="name">名前:</label>
        <input id="name" name="name" type="text" value={this.state.name} onChange={this.handleChange}></input>
        <br />

        <label htmlFor="prefecture">住所:</label>
        <select id="prefecture" name="prefecture" value={this.state.prefecture} onChange={this.handleChange}>
          <option value=""></option>
          <option value="tokyo">東京都</option>
          <option value="kanagawa">神奈川県</option>
          <option value="saitama">埼玉県</option>
          <option value="chiba">千葉県</option>
          <option value="ibaraki">茨城県</option>
          <option value="gunma">群馬県</option>
          <option value="tochigi">栃木県</option>
        </select>

        <fieldset>
          <legend>経験年数:</legend>
          <input id="career_zero" name="career" type="radio" value="zero" checked={this.state.career === "zero"} onChange={this.handleChange} />
          <label htmlFor="career_zero">未経験</label>
          <input id="career_one" name="career" type="radio" value="one" checked={this.state.career === "one"} onChange={this.handleChange} />
          <label htmlFor="career_one">1年未満</label>
          <input id="career_three" name="career" type="radio" value="three" checked={this.state.career === "three"} onChange={this.handleChange} />
          <label htmlFor="career_three">1~3年</label>
          <input id="career_five" name="career" type="radio" value="five" checked={this.state.career === "five"} onChange={this.handleChange} />
          <label htmlFor="career_five">3年~5年</label>
          <input id="career_over" name="career" type="radio" value="over" checked={this.state.career === "over"} onChange={this.handleChange} />
          <label htmlFor="career_over">5年以上</label>
        </fieldset>

        <fieldset>
          <legend>スキル:</legend>
          <input id="skill_java" name="skill" type="checkbox" value="java" checked={this.state.skill.includes("java")} onChange={this.handleChangeMulti} />
          <label htmlFor="skill_java">Java</label>
          <input id="skill_php" name="skill" type="checkbox" value="php" checked={this.state.skill.includes("php")} onChange={this.handleChangeMulti} />
          <label htmlFor="skill_php">PHP</label>
          <input id="skill_javascript" name="skill" type="checkbox" value="javascript" checked={this.state.skill.includes("javascript")} onChange={this.handleChangeMulti} />
          <label htmlFor="skill_javascript">Javascript</label>
          <input id="skill_python" name="skill" type="checkbox" value="python" checked={this.state.skill.includes("python")} onChange={this.handleChangeMulti} />
          <label htmlFor="skill_python">Python</label>
          <input id="skill_ruby" name="skill" type="checkbox" value="ruby" checked={this.state.skill.includes("ruby")} onChange={this.handleChangeMulti} />
          <label htmlFor="skill_ruby">Ruby</label>
        </fieldset>

        <br />
        <label htmlFor="memo">メモ:</label>
        <textarea id="memo" name="memo" value={this.state.memo} onChange={this.handleChange}></textarea>
        <br />

        <label htmlFor="file">ファイル:</label>
        <input id="file" name="file" type="file" ref={this.file}></input>
        <br />

        <button type="button" onClick={this.show}>
          送信
        </button>
      </form>
    );
  }
}

image.png

useStateを使ったフォーム

import React, { useState } from "react";

const App = () => {
  const [name, setName] = useState("");
  const [prefecture, setPrefecture] = useState("");
  const [career, setCareer] = useState("");
  const [skill, setSkill] = useState([]);
  const [memo, setMemo] = useState("");

  const file = React.createRef();

  const handleChange = (event) => {
    switch (event.target.name) {
      case "name":
        setName(event.target.value);
        break;
      case "prefecture":
        setPrefecture(event.target.value);
        break;
      case "career":
        setCareer(event.target.value);
        break;
      case "memo":
        setMemo(event.target.value);
        break;
      default:
        console.log("key not found");
    }
  };

  const handleChangeMulti = (e) => {
    if (skill.includes(e.target.value)) {
      setSkill(skill.filter((item) => item !== e.target.value));
    } else {
      setSkill([...skill, e.target.value]);
    }
  };

  const show = () => {
    console.log(name);
    console.log(prefecture);
    console.log(career);
    console.log(skill);
    console.log(memo);

    const f = file.current.files[0];
    if (f) {
      console.log(`${f.name} ${f.type}  ${f.size}`);
    }
  };

  return (
    <form>
      <label htmlFor="name">名前:</label>
      <input id="name" name="name" type="text" value={name} onChange={handleChange}></input>
      <br />

      <label htmlFor="prefecture">住所:</label>
      <select id="prefecture" name="prefecture" value={prefecture} onChange={handleChange}>
        <option value=""></option>
        <option value="tokyo">東京都</option>
        <option value="kanagawa">神奈川県</option>
        <option value="saitama">埼玉県</option>
        <option value="chiba">千葉県</option>
        <option value="ibaraki">茨城県</option>
        <option value="gunma">群馬県</option>
        <option value="tochigi">栃木県</option>
      </select>

      <fieldset>
        <legend>経験年数:</legend>
        <input id="career_zero" name="career" type="radio" value="zero" checked={career === "zero"} onChange={handleChange} />
        <label htmlFor="career_zero">未経験</label>
        <input id="career_one" name="career" type="radio" value="one" checked={career === "one"} onChange={handleChange} />
        <label htmlFor="career_one">1年未満</label>
        <input id="career_three" name="career" type="radio" value="three" checked={career === "three"} onChange={handleChange} />
        <label htmlFor="career_three">1~3年</label>
        <input id="career_five" name="career" type="radio" value="five" checked={career === "five"} onChange={handleChange} />
        <label htmlFor="career_five">3年~5年</label>
        <input id="career_over" name="career" type="radio" value="over" checked={career === "over"} onChange={handleChange} />
        <label htmlFor="career_over">5年以上</label>
      </fieldset>

      <fieldset>
        <legend>スキル:</legend>
        <input id="skill_java" name="skill" type="checkbox" value="java" checked={skill.includes("java")} onChange={handleChangeMulti} />
        <label htmlFor="skill_java">Java</label>
        <input id="skill_php" name="skill" type="checkbox" value="php" checked={skill.includes("php")} onChange={handleChangeMulti} />
        <label htmlFor="skill_php">PHP</label>
        <input id="skill_javascript" name="skill" type="checkbox" value="javascript" checked={skill.includes("javascript")} onChange={handleChangeMulti} />
        <label htmlFor="skill_javascript">Javascript</label>
        <input id="skill_python" name="skill" type="checkbox" value="python" checked={skill.includes("python")} onChange={handleChangeMulti} />
        <label htmlFor="skill_python">Python</label>
        <input id="skill_ruby" name="skill" type="checkbox" value="ruby" checked={skill.includes("ruby")} onChange={handleChangeMulti} />
        <label htmlFor="skill_ruby">Ruby</label>
      </fieldset>

      <br />
      <label htmlFor="memo">メモ:</label>
      <textarea id="memo" name="memo" value={memo} onChange={handleChange}></textarea>
      <br />

      <label htmlFor="file">ファイル:</label>
      <input id="file" name="file" type="file" ref={file}></input>
      <br />

      <button type="button" onClick={show}>
        送信
      </button>
    </form>
  );
};
export default App;

ライフサイクルメソッド

Mounting Updating Unmounting 用途
constructor(props) 初期化 stateの初期化、thisの固定など
render() 描画時 描画時 必須。React要素、文字列値、数値、など
componentDidMount() 配置後 リソースの初期化、文書ツリーへのアクセスなど
shouldComponentUpdate() 再描画前 再描画前にアクセスしたいとき
componentDidUpdate() 再描画後 再描画後にアクセスしたいとき
componentWillUnmount() 破棄時 リソースの破棄など

ルーティング

npm install react-router-dom
または
yarn add react-router-dom
import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";

export default function BasicRouter() {
  return (
    <Router>
      <div>

        {/* リンク表示部 リンクがここに表示される */}
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/dashboard">Dashboard</Link>
          </li>
        </ul>

        <hr />

        {/* コンポーネント表示部 パスがマッチングしたコンポーネントがここに表示される */}
        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/dashboard">
            <Dashboard />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

function Home() {
  return (
    <div>
      <h2>Home</h2>
    </div>
  );
}

function About() {
  return (
    <div>
      <h2>About</h2>
    </div>
  );
}

function Dashboard() {
  return (
    <div>
      <h2>Dashboard</h2>
    </div>
  );
}

image.png

ローカルストレージ

  • ローカルストレージ
    • 値 = localStorade.getItem(キー)
    • localStorade.setItem(キー, 値)
  • JSON⇔オブジェクト変換
    • オブジェクト = JSON.parse(JSON文字列)
    • JSON文字列 = JSON.stringify(オブジェクト)
  • || [] はnullの場合、[]にする。
// データ取得
componentDidMount() {
  const todos = JSON.parse(localStorade.getItem('todos')) || [];
  this.setState({todos: todos});
}
// データ1件追加
addTodo(todo) {
  const todos = this.state.todos;
  todos.push(todo);
  this.setState({todos: todos});
  localStorade.setItem('todos', JSON.stringify(this.state.todos));
}
// データ1件削除
deleteTodo(i) {
  const todos = this.state.todos;
  todos.splice(i, 1);
  this.setState({todos: todos});
  localStorade.setItem('todos', JSON.stringify(this.state.todos));
}

Fetch API

Read List

fetch("http://localhost:8080/todos")
.then((res) => res.json())
.then((data) => {
  this.setState({todos: data})
})
.catch((err) => console.log(err))

Read

fetch("http://localhost:8080/todos/${id}")
.then((res) => res.json())
.then((data) => {
  this.setState({todo: data})
})
.catch((err) => console.log(err))

Create

fetch("http://localhost:8080/todos" ,{
  method: "POST",
  headers: { "Content-type": "application/json" },
  body: JSON.stringify(todo)
})
.then((res) => res.json())
.then((data) => {
  // 処理
})
.catch((err) => console.log(err))

Update

fetch("http://localhost:8080/todos/${id}" ,{
  method: "PUT",
  headers: { "Content-type": "application/json" },
  body: JSON.stringify(todos)
})
.then((res) => res.json())
.then((data) => {
  // 処理
})
.catch((err) => console.log(err))

Delete

fetch("http://localhost:8080/todos/${id}" ,{
  method: "DELETE"
})
.then((res) => res.json())
.then((data) => {
  // 処理
})
.catch((err) => console.log(err))

今後追加したいこと
  • Redux
  • Hook
  • Spring Bootなどへの組み込み

参考
速習 React 速習シリーズ Kindle版
https://reactrouter.com/web/guides/quick-start

0
3
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
3