Site icon Bệ Phóng Việt

ReactJS Bài 6: Dùng table với dữ liệu động

lập trình reactjs dữ liệu trong table
Advertisements

Trong bài này, chúng ta sẽ học cách tạo bảng table, với dữ liệu động sử dụng reactjs. Chúng ta sẽ xem các thao tác lấy dữ liệu qua web service api và tạo các table row, sau đó là chức năng xoá dữ liệu kèm theo xoá row. Tất cả đều xử dụng reactjs component.

Chức năng

Chúng ta sẽ xây dựng chức năng quản lý danh sách việc cần làm (Todo List) đơn giản, tạm gọi là todo. Mỗi todo sẽ có id, name (tên việc), status (trạng thái). Trạng thái có thể là chưa xong (pending) hoặc đã xong (done).

Người sử dụng có thể tạo todo mới bằng cách nhập tên việc và trạng thái.

Danh sách các đầu việc sẽ được hiện ở dạng bảng.

Chúng ta sẽ dùng 3 api sau để ghi nhận thay đổi dữ liệu với cơ sở dữ liệu MySQL. Bạn có thể download và chạy backend được viết bằng Laravel tại đây.

  1. GET /api/todo: Lấy danh sách việc
  2. POST /api/todo: Tạo việc mới
  3. DELETE /api/todo/{id}: Xoá todo theo id

Tạo reactjs component cho table <table> và row <tr>

Trong thư mục src/componentstạo file TodoTable.js với đoạn code sau:

import React, { useState } from 'react';

function TodoTableRow({ id, name, status }) {
  return (
    <tr>
      <td>{name}</td>
      <td>{status == 1 ? <span>Done</span> : <span>Pending</span>}</td>
      <td>
        <input type="hidden" value={id}/>
        <button>Delete</button>
      </td>
    </tr>
  );
}

function TodoTable({todoData}) {
  const [rows, setRows] = useState(todoData);

  function handleAddRow() {
    setRows([...rows, { name: "", status: "" }]);
  }

  function handleChange(e, index) {
    const newRows = [...rows];
    newRows[index][e.target.name] = e.target.value;
    setRows(newRows);
  }

  return (
    <div>
      <table className='table'>
        <thead>
          <tr>
            <th>Name</th>
            <th>Status</th>
            <th>Action</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((row) => (
            <TodoTableRow
              id={row.id}
              name={row.name}
              status={row.status}
            />
          ))}
        </tbody>
      </table>
      <button onClick={handleAddRow}>Add Row</button>
    </div>
  );
}

export default TodoTable;

Component TodoTableRow là reacjts component được viết ở dạng function (“functional component”),

  1. TodoTableRow in ra HTML cho từng row của todo.
  2. TodoTableRow nhận vào ba props làm đầu vào: id, name, và status.
  3. Component này trả về một thẻ <tr>, trong đó có chứa ba thẻ <td>. Thẻ đầu tiên chứa giá trị của name, thẻ thứ hai chứa một <span> element với nội dung là “Done” nếu giá trị của status bằng 1, hoặc “Pending” nếu giá trị của status khác 1. Thẻ thứ ba chứa một input có kiểu là “hidden” với giá trị là id và một button với nội dung là “Delete”.

Reactjs component TodoTable:

  1. Nhận vào một prop todoData.
  2. Sử dụng useState để khởi tạo một state variable rows với giá trị là todoData. Chúng ta gán dữ liệu json của các todo vào todoData từ trang TodoList ở mục sau.
  3. Hàm handleAddRow để thêm một dòng với giá trị mặc định là { name: "", status: "" }.
  4. Còn hàm handleChange dùng để thay đổi giá trị của một dòng (không thuộc phần của bài học này).

 

Giao diện cho trang Todo

Tiếp theo chúng ta xây dựng giao diện cho trang Todo sử dụng reactjs cơmponent. Múc đích của trang là lấy dữ liệu từ server và gọi component TodoTable ở trên để in dữ liệu ra màn hình.

Trong thư mục src/screensthêm file TodoList.js với đoạn code dưới đây:

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import TodoTable from '../components/TodoTable';
import 'bootstrap/dist/css/bootstrap.min.css';
import DefaultLayout from '../layouts/DefaultLayout';

function TodoList() {
  const [todoData, setTodoData] = useState([]);

  useEffect(() => {
    async function fetchData() {
      const response = await axios.get('http://localhost:5051/api/todo');
      setTodoData(response.data);
    }
    fetchData();
  }, []);

  return (
    <DefaultLayout title="To-do List">
      {todoData.length ? <TodoTable todoData={todoData} /> : <div> Loading... </div> }
    </DefaultLayout>
  );
}

export default TodoList;

Đoạn code này định nghĩa reactjs component TodoList, cũng là màn hình chính của chức năng quản lý todo này.

  1. useState khởi tạo một biến todoData (trong reactjs gọi là state variable) với giá trị ban đầu là một mảng rỗng.
  2. useEffect dùng axios để API tại http://localhost:5051/api/todo và cập nhật todoData với dữ liệu json trả về từ API.
  3. Trong render method return, component này sử dụng DefaultLayout component chúng ta đã xây dựng ở bài trước để hiển thị nội dung với tiêu đề là “To-do List”. Nó cũng sử dụng TodoTable component để hiển thị bảng với dữ liệu là todoData , nếu dữ liệu todoData không tồn tại, ứng dụng sẽ hiển thị thông báo ‘Loading…’.

Bạn nhớ cài đặt Laravel api, chạy backend server. Sau đó bạn có thể chạy thử ứng dụng reactjs của mình và sẽ thấy kết quả giống như màn hình dưới đây:

Giải thích thêm về reactjs useEffect

useEffect là một Hook trong React được sử dụng để giải quyết các tác vụ có ảnh hưởng tới các thành phần trong một component, chẳng hạn như gọi API, tương tác với DOM hoặc lưu trữ trạng thái. useEffect của reactjs cho phép bạn “đăng ký” một hàm để chạy sau khi component đã được render lần đầu và sau mỗi lần render tiếp theo.

Sử dụng useEffect trong TodoList component: khi component này được render lần đầu, nó sẽ gọi hàm fetchData để lấy dữ liệu từ API và cập nhật todoData state variable. Khi component được render lại với giá trị mới của todoData, nó sẽ giải quyết tác vụ cập nhật UI với dữ liệu mới.

Trong reactjs, useEffect có 2 tham số chính:

  1. Tham số đầu tiên là hàm side-effect (thường là một async function) mà bạn muốn chạy sau mỗi lần render. Hàm này có thể truy cập vào props và state của component.
  2. Tham số thứ hai là một mảng các giá trị state hoặc props mà bạn muốn theo dõi. Nếu bạn không chỉ định giá trị nào, hàm sẽ chạy sau mỗi lần render. Nếu bạn chỉ định một giá trị, hàm sẽ chạy sau khi giá trị đó thay đổi.

Đọc thêm về useEffect của reactjs tại đây.

Xây dựng chức năng thêm mới

Để có thêm chức năng thêm 1 Todo mới, chúng ta cần update form cuối bảng để nhận vào 2 input là name và status của todo. Sau đó submit form và gọi api POST /api/todo/để lưu dữ liệu vào cơ sở dữ liệu trên server. Sau khi lưu thành công, cập nhật bảng trên giao diện.

Cập nhật form cuối bảng như sau:

<table>
...
</table>
<div className="row g-3">
  <div className="col-auto">
    <input type="text" className='form-control' name="name" value={newTodo.name} onChange={handleChange} placeholder="Name" />
  </div>
  <div className="col-auto">
    <select name="status" className='form-control' value={newTodo.status} onChange={handleChange}>
      <option>Select</option>
      <option value={0}>Pending</option>
      <option value={1}>Done</option>
    </select>
  </div>
  <div className="col-auto">
    <button onClick={handleAddTodo} className='btn btn-primary mb-3'>Add</button>
  </div>
</div>

Cập nhật hàm handleChange:

function handleChange(e) {
  setNewTodo({
    ...newTodo,
    [e.target.name]: e.target.value
  });
}

Thêm hàm handleAddTodo:

async function handleAddTodo() {
  try {
    const response = await axios.post('http://localhost:5051/api/todo', newTodo);
      setRows([...rows, response.data]);
      setNewTodo({ name: '', status: '' });
  } catch (err) {
    console.error(err);
  }
}

Đoạn code trên là hàm handleAddTodo được gọi khi người dùng nhấn nút “Add” để thêm todo mới vào danh sách. Hàm này sử dụng axios để gửi một yêu cầu POST đến api /api/todo với dữ liệu là todo mới được nhập từ form (newTodo).

Với hàm này, sau khi thêm thành công, todo mới sẽ được thêm vào state rows và hiển thị trên giao diện, form sẽ được reset lại để người dùng có thể thêm todo tiếp theo.

Github code

Bạn có thể download code của toàn bộ series lập trình reactjs tại đây.

Bài tiếp theo

ReactJS Bài 7: Dùng logging để ghi lại thông tin, giúp gỡ rối hiệu quả

Lời kết

Và cuối cùng, người ta nói thái độ là tất cả. Vì thế bạn đừng quên các kỹ năng mềm quan trọng sau nếu muốn có 1 sự nghiệp thành công: 5 Kỹ năng mềm cần thiết cho lập trình viên muốn thành team lead

Exit mobile version