サイトアイコン 上尾市のWEBプログラマーによるブログ

「ReactでCRUD操作を行ってみよう」の感想・備忘録

kindle本「ReactでCRUD操作を行ってみよう」のまとめ。

点数

71点

感想

前半はRESTやFetch APIの説明であり、実質は後半のみだった。

簡単な内容ばかりで、少々物足りなく感じた。

REST API

CRUDのHTTPメソッドとURIが紹介されているサイト

JSONPlaceholder - Free Fake REST API

CRUD操作のHTTPメソッド、URI、レスポンスは以下のようになる

CRUDHTTPメソッドURI成功時のステータスコード
登録POST/posts201
取得GET/posts, /posts/100200
更新PUT/posts/100204
削除DELETE/posts/100204

PostmanというWeb APIのテストやドキュメント作成ができるソフトがある

https://www.postman.com/downloads/

※実行時にユーザー登録を求められるが、一番下のSki signing…でスキップできる

JSON Server

REST APIのモックを簡単に作ることができるNode.jsライブラリ。

インストール

npm install json-server

以下のようなJSONファイルを用意

{
  "sites": [
    {
      "id": 1,
      "name": "Google",
      "url": "https://google.com"
    }
  ]
}

実行

json-server --watch JSONファイル

実行すると以下のようなURLでREST APIにアクセスできるようになる。

Fetch API

// GET
fetch('https://jsonplaceholder.typicode.com/users/1')
  .then((res) => res.json())
  .then((user) => console.log(user.name))
  .catch((err) => console.log(err));
// POST
fetch('./get-json.php', {
  method: 'POST',
  headers: {
    'Content-type': 'application/json'
  },
  body: JSON.stringify({id: 555})
})
  .then((res) => {
    console.log(res.status);
    return res.json()
  })
  .then((data) => console.log(data))
  .catch((err) => console.log(err));

ReactでCRUD

  1. npm init -y; npm install create-react-app
  2. npx create-react-app crud-app
  3. App.jsを修正
  4. json-server --watch JSONファイル
    (JSON Serverサーバの起動)
  5. npm start
    JSON Serverとは別コンソールで行う。
    ポート3000が使用中のため別ポートの使用を求められるのでyを入力。
import React, {Component} from 'react';
import logo from './logo.svg';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      siteName: '',
      siteURL: '',
      sites: [],
    }
  }

  componentDidMount() {
    fetch('http://localhost:3000/sites')
      .then((res) => res.json())
      .then((sites) => this.setState({sites: sites}))
      .catch((err) => console.log(err));
  }

  handleNewNameInput = (e) => {
    this.setState({siteName: e.target.value});
  }

  handleNewUrlInput = (e) => {
    this.setState({siteURL: e.target.value});
  }

  handleCreateData = () => {
    if (this.state.siteName === '' || this.state.siteURL === '') {
      return;
    }
    fetch('http://localhost:3000/sites', {
      method: 'POST',
      headers: {
        'Content-type': 'application/json'
      },
      body: JSON.stringify({name: this.state.siteName, url: this.state.siteURL})
    })
      .then((res) => res.json())
      .then((site) => {
        const sites = this.state.sites;
        sites.push(site);
        this.setState({
          sites: sites,
          siteName: '',
          siteURL: ''
        })
      })
      .catch((err) => console.log(err));
  }

  render() {
    return (
      <div>
        <p><input type="text" value={this.state.siteName} onChange={this.handleNewNameInput} placeholder="Name"/></p>
        <p><input type="text" value={this.state.siteURL} onChange={this.handleNewUrlInput} placeholder="URL"/></p>
        <p>
          <button onClick={this.handleCreateData}>Create</button>
        </p>
        <h3>Todoリスト</h3>
        <ul>
          {
            this.state.sites.map((site, i) => {
              return (
                <li key={site.url}>{i} {site.name} {site.url}</li>
              )
            })
          }
        </ul>
      </div>
    );
  }
}

export default App;

ルーティングを追加

  1. npm install react-router-dom
  2. コンポーネントSiteListとAddListを追加しApp.jsにルーティングを追加
import React, {Component} from 'react';

class SiteList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      sites: [],
    }
  }

  componentDidMount() {
    fetch('http://localhost:3000/sites')
      .then((res) => res.json())
      .then((sites) => this.setState({sites: sites}))
      .catch((err) => console.log(err));
  }

  render() {
    return (
      <div>
        <p><a href="/sites/add">登録フォームへ</a></p>
        <h3>Siteリスト</h3>
        <ul>
          {
            this.state.sites.map((site, i) => {
              return (
                <li key={site.url}>{i} {site.name} {site.url}</li>
              )
            })
          }
        </ul>
      </div>
    );
  }
}

export default SiteList;
import React, {Component} from 'react';

class AddSite extends Component {
  constructor(props) {
    super(props);
    this.state = {
      siteName: '',
      siteURL: '',
    }
  }

  handleNewNameInput = (e) => {
    this.setState({siteName: e.target.value});
  }

  handleNewUrlInput = (e) => {
    this.setState({siteURL: e.target.value});
  }

  handleCreateData = () => {
    if (this.state.siteName === '' || this.state.siteURL === '') {
      return;
    }
    fetch('http://localhost:3000/sites', {
      method: 'POST',
      headers: {
        'Content-type': 'application/json'
      },
      body: JSON.stringify({name: this.state.siteName, url: this.state.siteURL})
    })
      .then((res) => res.json())
      .then(() => {
        this.setState({
          siteName: '',
          siteURL: ''
        })
      })
      .catch((err) => console.log(err));
  }

  render() {
    return (
      <div>
        <p><a href="/">Siteリストへ</a></p>
        <h3>登録フォーム</h3>
        <p><input type="text" value={this.state.siteName} onChange={this.handleNewNameInput} placeholder="Name"/></p>
        <p><input type="text" value={this.state.siteURL} onChange={this.handleNewUrlInput} placeholder="URL"/></p>
        <p>
          <button onClick={this.handleCreateData}>Create</button>
        </p>
      </div>
    );
  }
}

export default AddSite;
import React, {Component} from 'react';
import { Route, BrowserRouter } from 'react-router-dom';
import SiteList from './SiteList';
import AddSite from './AddSite';

class App extends Component {
  render() {
    return (
      <BrowserRouter>
        <Route path="/" component={SiteList} exact/>
        <Route path="/sites/add" component={AddSite} exact/>
      </BrowserRouter>
    );
  }
}

export default App;

Bootstrapを追加

index.htmlに追加

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

任意のタグにclassName属性を追加

※ class属性ではないので注意

Loop Back

ログイン認証用REST APIのモックを簡単に作ることができるNode.jsライブラリ。

  1. インストール
    npm install loopback-cli
  2. アプリケーション作成(プロジェクトのようなもの)
    lb
  3. カレントディレクトリの変更
    cd アプリ名
  4. 実行
    node .
    ※表示されるURLにアクセスすることでAPI一覧の確認が可能
モバイルバージョンを終了