0
0

More than 1 year has passed since last update.

React(Node js + MySQL)の構成でアプリを作成をしました【簡単なCRUDアプリケーション】

Last updated at Posted at 2022-10-11

環境の準備

mkdir <ファイル名>
cd <ファイル名>
npm init -y  //package.jsonファイルを作成
npm i express mysql2 sequelize cors
npm i --save-dev nodemon
//新しいtarminalを作成する
npx create-react-app <ファイル名>
cd <ファイル名>
npm i react-router-dom axios bulma

コンポーネント・ファイル構成

backend
  ├─ config
       └── Database.js
  ├─ controllers
       └── UserController.js
  └── models
       └── UserModel.js
frontend
    ├─ src
       ├─ components
            ├── AddUser.jsx
            ├── EditList.jsx
            └── UserList.jsx
   ├── App.tsx
   └── index.tsx

backend/config/Database.js
import { Sequelize } from 'sequelize';

const db = new Sequelize('crud_db', 'root', '', {
  host: 'localhost',
  dialect: 'mysql',
});

export default db;
backend/controllers/UserController.js
import User from '../models/UserModel';

export const getUsers = async (req, res) => {
  try {
    const response = await User.findAll();
    res.status(200).json(response);
  } catch (error) {
    console.log(error.message);
  }
};

export const getUserById = async (req, res) => {
  try {
    const response = await User.findOne({
      where: {
        id: req.params.id,
      },
    });
    res.status(200).json(response);
  } catch (error) {
    console.log(error.message);
  }
};

export const createUser = async (req, res) => {
  try {
    await User.create(req.body);
    res.status(201).json({ msg: 'User Created' });
  } catch (error) {
    console.log(error.message);
  }
};

export const updateUser = async (req, res) => {
  try {
    await User.update(req.body, {
      where: {
        id: req.params.id,
      },
    });
    res.status(200).json({ msg: 'User Updated' });
  } catch (error) {
    console.log(error.message);
  }
};

export const deleteUser = async (req, res) => {
  try {
    await User.destroy(req.body, {
      where: {
        id: req.params.id,
      },
    });
    res.status(200).json({ msg: 'User Deleted' });
  } catch (error) {
    console.log(error.message);
  }
};
backend/models/UserModel.js
import { Sequelize } from 'sequelize';
import db from '../config/Database';

const { DataTypes } = Sequelize;

const User = db.define(
  'users',
  {
    name: DataTypes.STRING,
    email: DataTypes.STRING,
    gender: DataTypes.STRING,
  },
  {
    freezeTableName: true,
  }
);

export default User;

(async () => {
  await db.sync();
})();
frontend/ src/ components/ AddUser.jsx
import React, { useState } from 'react';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';

const AddUser = () => {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [gender, setGender] = useState('Male');
  const navigate = useNavigate();

  const saveUser = async (e) => {
    e.preventDefault();
    try {
      await axios.post('http://localhost:5000/users', { name, email, gender });
      navigate('/');
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <div className='mt-5 columns is-centered'>
      <div className='column is-half'>
        <form onSubmit={saveUser}>
          <div className='field'>
            <label className='label'>Name</label>
            <div className='control'>
              <input
                type='text'
                className='input'
                value={name}
                onChange={(e) => setName(e.target.value)}
                placeholder='Name'
              />
            </div>
          </div>
          <div className='field'>
            <label className='label'>Email</label>
            <div className='control'>
              <input
                type='text'
                className='input'
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                placeholder='Email'
              />
            </div>
          </div>
          <div className='field'>
            <label className='label'>Gender</label>
            <div className='control'>
              <div className='select is-fullwidth'>
                <select
                  value={gender}
                  onChange={(e) => setGender(e.target.value)}
                >
                  <option value='Male'>Male</option>
                  <option value='Female'>Female</option>
                </select>
              </div>
            </div>
          </div>
          <div className='field'>
            <button type='submit' className='button is-success'>
              Save
            </button>
          </div>
        </form>
      </div>
    </div>
  );
};

export default AddUser;
frontend/ src/ components/ EditList.jsx
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useNavigate, useParams } from 'react-router-dom';

const EditUser = () => {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [gender, setGender] = useState('Male');
  const navigate = useNavigate();
  const { id } = useParams();

  useEffect(() => {
    getUserById();
  }, []);

  const updateUser = async (e) => {
    e.preventDefault();
    try {
      await axios.patch(`http://localhost:5000/users/${id}`, {
        name,
        email,
        gender,
      });
      navigate('/');
    } catch (error) {
      console.log(error);
    }
  };

  const getUserById = async () => {
    const response = await axios.get(`http://localhost:5000/users/${id}`);
    setName(response.data.name);
    setEmail(response.data.email);
    setGender(response.data.gender);
  };

  return (
    <div className='mt-5 columns is-centered'>
      <div className='column is-half'>
        <form onSubmit={updateUser}>
          <div className='field'>
            <label className='label'>Name</label>
            <div className='control'>
              <input
                type='text'
                className='input'
                value={name}
                onChange={(e) => setName(e.target.value)}
                placeholder='Name'
              />
            </div>
          </div>
          <div className='field'>
            <label className='label'>Email</label>
            <div className='control'>
              <input
                type='text'
                className='input'
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                placeholder='Email'
              />
            </div>
          </div>
          <div className='field'>
            <label className='label'>Gender</label>
            <div className='control'>
              <div className='select is-fullwidth'>
                <select
                  value={gender}
                  onChange={(e) => setGender(e.target.value)}
                >
                  <option value='Male'>Male</option>
                  <option value='Female'>Female</option>
                </select>
              </div>
            </div>
          </div>
          <div className='field'>
            <button type='submit' className='button is-success'>
              Updata
            </button>
          </div>
        </form>
      </div>
    </div>
  );
};

export default EditUser;
frontend/ src/ components/ UserList.jsx
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { Link } from 'react-router-dom';

const UserList = () => {
  const [users, setUser] = useState([]);

  useEffect(() => {
    getUsers();
  }, []);

  const getUsers = async () => {
    const response = await axios.get('http://localhost:5000/users');
    setUser(response.data);
  };

  const deleteUser = async (id) => {
    try {
      await axios.delete(`http://localhost:5000/users/${id}`);
      getUsers();
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <div className='mt-5 columns is-centered'>
      <div className='column is-half'>
        <Link to={`add`} className='button is-success'>
          Add New
        </Link>
        <table className='table is-striped is-fullwidth'>
          <thead>
            <tr>
              <th>No</th>
              <th>Name</th>
              <th>Email</th>
              <th>Gender</th>
              <th>Actions</th>
            </tr>
          </thead>
          <tbody>
            {users.map((user, index) => (
              <tr key={user.id}>
                <td>{index + 1}</td>
                <td>{user.name}</td>
                <td>{user.email}</td>
                <td>{user.gender}</td>
                <td>
                  <Link
                    to={`edit/${user.id}`}
                    className='button is-small is-info'
                  >
                    Edit
                  </Link>
                  <button
                    onClick={() => deleteUser(user.id)}
                    className='button is-small is-danger'
                  >
                    Delete
                  </button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
};

export default UserList;
frontend/ src/ App.js
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import AddUser from './components/AddUser';
import UserList from './components/UserList';
import EditUser from './components/EditUser';

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path='/' element={<UserList />} />
        <Route path='add' element={<AddUser />} />
        <Route path='edit/:id' element={<EditUser />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

frontend/ src/ index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import 'bulma/css/bulma.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

参考サイト

Tutorial LENGKAP CRUD dengan Node JS, Express, React JS, dan MySQL (Full Stack)

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