Rest-based App React

Rest-based App React hướng dẫn bạn tạo ứng dụng để tương tác với API server nhằm quản lý data qua các thao tác xem, thêm sửa xóa dữ liệu.  Ứng dụng react của bạn sẽ là phần front end tương tác với back end là các server  API

Thiết lập api server

Api server là các server phục vụ các request từ xa qua http để cung cấp dữ liệu có cấu trúc cho client. Json-server  là một thư viện nodeJS giúp bạn tạo SPI server đơn gỉan, đủ tính năng để dùng ở local.

Cài đặt json-server

 npm install json-server

Xem tài liệu hướng dẫn dùng json server

Json-server hỗ trợ thêm record, cập nhật record, xóa record, lấy chi tiết 1 record, lấy danh sách record, sort, phân trang, filter. Xem tài liệu đầy đủ ở đây:  https://www.npmjs.com/package/json-server

Tạo file dữ liệu cho json server

File database cho json-server là 1 file text. Chứa dữ liệu là mảng các object json. Mỗi mảng có 1 tên (loaisach, sach).  Mời bạn tạo file text và lưu với tên sachHay.json , sau đó code:

{
 "loaisach": [
    {"id":"6","tenloai":"Nghệ thuật sống","thutu":"1","anhien":"1"},
    {"id":"2","tenloai":"Lịch sử","thutu":"2","anhien":"1"},
    {"id":"3","tenloai":"Thiếu nhi","thutu":"4","anhien":"1"},
 ],
 "sach": [
    {"id":"55","tensach":"Núi xanh nay vẫn đó","gia":"198000","urlHinh":"",
     "idLoai":"2","xem":"535","hot":"0","moi":"0","mota":""},
    {"id":"58","tensach":"Có 500 Năm Như Thế","gia":"124950","urlHinh":"",
     "idLoai":"2","xem":"560","hot":"0","moi":"0","mota":""},
    {"id":"105","tensach":"Sức Mạnh Của Sự Tử Tế","gia":"68000","urlHinh":"",
     "idLoai":"6","xem":"751","hot":"0","moi":"0","mota":""},
 ],
 "profile": {"ten": "sachHay","tacgia": "Nguyen Van Long" }
}

Chạy json-server

Mở command line, chuyển vào folder chứa file  mới tạo và viết lệnh chạy json-server , truyền tham số là file database và giá trị port cho nó hoạt động:

json-server -w sachHay.json -p 3500

Test api server

Mở trình duyệt và gõ http://localhost:3500

Test Api server

Các chức năng json-server cung cấp qua API

Bảng sau mô tả các http method, đường dẫn và kết quả trả về của json- server đối với dữ liệu sách

Tạo project react để thực tập

  • Tạo project mới để thực tập
  • Chuyển vào project mới tạo và chạy npm start
  • Mở index.html và nhúng bootstrap css vào
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
  • Mở App.js và code tạo layout
import './App.css';
function App() {
  return (
   <div className="container">
     <header className="row"> HEADER </header>
     <main className="row">
       <article className="col-sm-9 bg-info"> 
       </article>
       <aside  className="col-sm-3 bg-secondary"> 
       </aside>
     </main>
   </div>
  );
}
export default App;

Định dạng trong App.css

header { background: darkcyan; height: 90px; position: relative;}
main { min-height: 500px;}

Xem kết quả:

Chức năng lấy danh sách record trong rest-based app react

Để lấy danh sách record loaisach, bạn request đến api server với method là GET. route là loaisach. Khi dữ liệu về, bạn gán vào state của component để dùng (hoặc có thể send lên store của redux)

a. Trong App.js, code nhúng component ListLoaiSach vào

b. Tạo component  ListLoaiSach.js để hiện các loại sách

import React from "react";
class ListLoaiSach extends React.Component {
  constructor(props){
    super(props);
    this.state = {listLoaiSach:null}
  }
  render() {
     let kq=  null;    
     return (kq);
  };
};
export default ListLoaiSach;

c. Sau hàm constructor, định nghĩa làm lấy dữ liệu từ API về , lưu vào state listLoaiSach

componentDidMount(){
    let url="http://localhost:3500/loaisach";
    fetch(url).then(res => res.json()).then(data => {      
      this.setState({listLoaiSach:data}); 
    });
}

d. Code lại hàm render để hiện dữ liệu

render() {
     let kq=  null;    
     if (this.state.listLoaiSach!==null)
     kq= <div className="listLoaiSach">
      { this.state.listLoaiSach.map( loai =>(
        <div className='MotLoaiSach' key={loai.id}>
            <div>{loai.tenloai}</div>    
            <div>{loai.thutu}</div>    
            <div>{loai.anhien===1? "Đang hiện":"Đang ẩn"}</div>    
            <div className="button">          
            <button type='button' className='btn btn-sm btn-danger'> Xóa </button>
            <button type='button' className='btn btn-sm btn-primary'> Sửa </button>
            </div>
        </div>
      ))            
      }
      </div>
      return (kq);
};

Định dạng trong App.css

.MotLoaiSach { 
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    grid-gap: 3px;
}
.MotLoaiSach >div { border: 0.5px solid black; padding: 3px 5px; margin-top: 3px; }
.MotLoaiSach >div:nth-child(2) { text-align:center;}
.MotLoaiSach >div:nth-child(3) { text-align:center;}
.MotLoaiSach >div:last-child{ text-align: right;}

Chạy trang sẽ thấy

Chức năng xóa 1 record

Để xóa 1 record loaisach, bạn request đến api server với method là DETETE route là loaisach/:id  

a. Trong component ListLoaiSach, định nghĩa hàm xoaLoaiSach, sau khi xóa xong, nếu muốn cập nhật cách loại sách đang hiện thì thực hiện xóa record trong state:

xoaLoaiSach(id=1) {    
    let url=`http://localhost:3500/loaisach/${id}`;
    fetch(url, {method:"DELETE"} ).then(res => res.json()).then(data => { 
      let arr = this.state.listLoaiSach.filter( s => {
        if (s.id===id) return false; else return true;
      })
      this.setState({listLoaiSach:arr});
    });    
}

b. Code gọi hàm trong nút Xóa

onClick={()=>this.xoaLoaiSach(loai.id)} 

Chức năng sửa 1 record

Để sửa 1 record loaisach, bạn request đến api server với method là PUT route là loaisach/:id  và trong body request là chuỗi JSON của loại cần cập nhật

a. Trong component ListLoaiSach, định nghĩa hàm suaLoaiSach, hàm nhận id của loại cần sửa rồi record tương ứng để gửi ra ngoài component cha xử lý. Component cha sẽ render form sửa loai sách ra trang web.

suaLoaiSach(id=1) { 
    let index = this.state.listLoaiSach.findIndex( (ls) => { return ls.id===id})
    let loaisach = this.state.listLoaiSach[index];    
    this.props.capnhat(loaisach)
}

b. Code gọi hàm trong nút Sửa

 onClick={()=>this.suaLoaiSach(loai.id)} 

Mỗi khi nhắp núit Sửa, hàm suaLoaiSach chạy, hàm này gọi hàm capnhat của component cha. Hàm capnhat ngoài component cha sẽ render form sửa loại sách cho bạn. Hãy test bằng cch nhắp nút Sửa, bạn sẽ thấy báo lỗi tại lệnh this.props.capnhat do chưa định nghĩa hàm này

c. Định nghĩa props capnhat trong App.js + hàm updateLoaiSach + vị trí hiện form sửa loại,

d. Tạo component SuaLoaiSach

import React from "react";
class SuaLoaiSach extends React.Component {  
  constructor(props){ super();
      this.state = {loaisach:{} }      
      this.tenloai =  React.createRef();
      this.thutu =  React.createRef();      
      this.anhien =  React.createRef();      
  }
  render() {
    return (
    <div className="suaLoaiSach m-2">
       <div className="mb-3">
        <input className="form-control" placeholder="Tên loại sách" 
        ref={this.tenloai} defaultValue={this.props.loaisach.tenloai} />
       </div>
       <div className="mb-3">
        <input className="form-control" placeholder="Thứ tự"
         ref={this.thutu} defaultValue={this.props.loaisach.thutu}/>
       </div>
       <div className="mb-3">
        <input className="form-control" placeholder="Ẩn hiện"
         ref={this.anhien} defaultValue={this.props.loaisach.anhien}/>
       </div>
       <div className="mb-3">
          <button type="button" className="btn btn-primary" >
          Sửa Loại Sách
          </button>
        </div>
    </div>
  )}
};
export default SuaLoaiSach;

e. Định nghĩa hàm hamSuaLoaiSach

hamSuaLoaiSach = () => {  
    let loaisach = {
      id: this.props.loaisach.id,
      tenloai: this.tenloai.current.value,
      thutu: this.thutu.current.value,
      anhien: this.anhien.current.value,      
    }
    let idLoaiSach = this.props.loaisach.id;
    let url=`http://localhost:3500/loaisach/${idLoaiSach}`;    
    fetch(url, {  method:"PUT", 
                  body:JSON.stringify(loaisach), 
                  headers:{'Content-Type':'application/json'}
               } 
    )
    .then(res => res.json())
    .then( d => console.log("Đã cập nhật xong", d));    
}

f. Code gọi hàm trong nút Sửa Loại Sách

onClick={this.hamSuaLoaiSach}

Test: chạy project: nhắp nút Sửa, sẽ thấy form Sửa loại sách. Nhập giá trị mới trong form rồi nhắp nút Sửa Loại Sách, sẽ cập nhật lên API Server. Bạn nạp lại trang web sẽ thấy thay đổi.

Chức năng thêm 1 record trong rest-based app react

Để thêm 1 record loaisach, bạn request đến api server với method là POST route là loaisach/:id  và trong body request là chuỗi JSON của loại cần thêm

a. Tạo component ThemLoaiSach , giống như component SuaLoaiSach, nhưng không cần defaultValue cho các input, idLoaiSach bạn có thể cho user nhập trong form hoặc tự phát sinh.

b. Cho hiện component ra layout: bạn có thể cho hiện ở đâu tùy ý, có thể cho hiện khi nhắp nút Thêm loại thì tốt

c. Khi nhắp nút Thêm trong form, code để gọi API như hình trên

Mời bạn thực hiện thêm

  • Mỗi lần cập nhật loại sách hoặc thêm loại sách thì cho render lại component list loại sách để thấy ngay kết quả cập nhật
  • Thêm title cho các field trong component  list loại sách
  • Thực hiện chức năng xem chi tiết 1 record
  • Có thế áp dụng thêm redux nếu muốn. 
  • Áp dụng sort, phân trang trong component list loại sách