Skip to the content.

03: Conditional and List Rendering

Table of contents


1. Conditional Rendering

Khác với Angular hay VueJS cung cấp cho chúng ta các directive như *ngIf hay v-if, React không có những directive như vậy và chúng ta sẽ sử dụng js conditional (if else).

Everything is Javascript!

Preparation (Lưu ý mình lấy ví dụ với functional component nha, với classed-base component sẽ có một vài khác biêt các bạn thử thực hành cho quen tay nhé hihe):

// App.js
// Add showPerson and togglePerson function
const [showPerson, setShowPerson] = useState(false);

const togglePerson = () => {
  setShowPerson(!showPerson);
};

Có cách để sử dụng như sau:

1. Sử dụng toán tử &&:

// App.js
return (
  <div className='App'>
    <h1>React Sample App</h1>
    <button onClick={togglePerson} style={btnStyle}>
      Toggle Person
    </button>
    {showPerson && (
      <Person name={person.name} click={changePerson} change={changeNameHandle}>
        {statement}
      </Person>
    )}
  </div>
);

Trong Javascript, khi thực thi condition đầu tiên nếu false thì sẽ không thực hiện condition tiếp theo.

2. Sử dụng Conditional (ternary) operator: condition ? exprIfTrue : exprIfFalse

{
  showPerson ? (
    <Person name={person.name} click={changePerson} change={changeNameHandle}>
      {statement}
    </Person>
  ) : null;
}

3. Sử dụng if - else thông thường

let personElement = null;

if (showPerson) {
  personElement = (
    <Person name={person.name} click={changePerson} change={changeNameHandle}>
      {statement}
    </Person>
  );
}

return (
  <div className='App'>
    <h1>React Sample App</h1>
    <button onClick={togglePerson} style={btnStyle}>
      Toggle Person
    </button>
    {personElement}
  </div>
);

Hoặc

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

Với 3 cách trên, tùy vào từng ngữ cạnh cụ thể các bạn hãy chọn ra các thức phù hợp nha.

2. List Rendering

2.1. List rendering basic syntax

Để render một list chúng ta sẽ sử dụng Array.map() function. Chi tiết về map() các bạn xem lại trong day-01 nha. Mình sẽ lấy một ví dụ ngắn, đơn giản như sau

const numbers = [1, 2, 3, 4, 5];

return (
  <ul>
    {numbers.map((number, index) => (
      <li key={index}>{number}</li>
    ))}
  </ul>
);

Keys giúp React xác định được item nào được add, changed hoặc removed. Chú ý là mỗi key trong một vòng lặp phải khác nhau và nếu thiếu key console sẽ báo lỗi đó nha.

Key must be unique

2.2. List rendering advanced

Giờ chúng ta quay trở lại với ví dụ về person ban đầu. Khởi tạo với một mảng persons:

// App.js
const [persons, setPersons] = useState([
  { id: 1, name: 'Iron man' },
  { id: 2, name: 'Doctor Strange' },
  { id: 3, name: 'Captain America' },
]);

và return:

return (
  <div className='App'>
    <h1>React Sample App</h1>
    <button onClick={togglePerson} style={btnStyle}>
      Toggle Person
    </button>
    {showPerson &&
      persons.map((person) => (
        <Person
          key={person.id}
          name={person.name}
          click={changePerson}
          change={changeNameHandle}
        >
          {statement}
        </Person>
      ))}
  </div>
);

Lúc này, changePerson()changeNameHandle() chưa hoạt động, chúng ta cần update hai function này. Để thay đổi name của một object person trong một mảng chúng ta sẽ cần truyền vào id của person đó khi gọi hàm:

<Person
  key={person.id}
  name={person.name}
  click={() => deletePerson(person.id)}
  change={(event) => changeNameHandle(event, person.id)}
>
  {statement}
</Person>

Cuối cùng là update các function:

const deletePerson = (id) => {
  const personIndex = persons.findIndex((p) => p.id === id);
  const newPersons = [...persons]; // Copy object, try to avoid reference and mutate it directly
  newPersons.splice(personIndex, 1); // Delete array element
  setPersons(newPersons);
};

const changeNameHandle = (event, id) => {
  const personIndex = persons.findIndex((p) => p.id === id);
  const person = { ...persons[personIndex] }; // Copy object, try to avoid reference and mutate it directly
  person.name = event.target.value;
  const newPersons = [...persons];
  newPersons[personIndex] = person;
  setPersons(newPersons);
};

Vì chúng ta không được change state một cách trực tiếp nên sẽ phải đi lòng vòng một chút nha.

Dưới đây là toàn bộ file App.js, tham khảo nếu bạn gặp lỗi nha:

import React, { useState } from 'react';
import './App.css';
import Person from './components/person/Person';

const App = () => {
  // State Declaration
  const [persons, setPersons] = useState([
    { id: 1, name: 'Iron man' },
    { id: 2, name: 'Doctor Strange' },
    { id: 3, name: 'Captain America' },
  ]);

  const [showPerson, setShowPerson] = useState(false);
  const [statement] = useState('Love you 3000!');

  const deletePerson = (id) => {
    const personIndex = persons.findIndex((p) => p.id === id);
    const newPersons = [...persons]; // Copy object, try to avoid reference and mutate it directly
    newPersons.splice(personIndex, 1);
    setPersons(newPersons);
  };

  const changeNameHandle = (event, id) => {
    const personIndex = persons.findIndex((p) => p.id === id);
    const person = { ...persons[personIndex] }; // Copy object, try to avoid reference and mutate it directly
    person.name = event.target.value;
    const newPersons = [...persons];
    newPersons[personIndex] = person;
    setPersons(newPersons);
  };

  const togglePerson = () => {
    setShowPerson(!showPerson);
  };

  const btnStyle = {
    backgroundColor: '#20232a',
    color: '#61dafb',
    padding: '8px 16px',
    border: 'none',
    borderRadius: '4px',
    cursor: 'pointer',
  };

  return (
    <div className='App'>
      <h1>React Sample App</h1>
      <button onClick={togglePerson} style={btnStyle}>
        Toggle Person
      </button>
      {showPerson &&
        persons.map((person) => (
          <Person
            key={person.id}
            name={person.name}
            click={() => deletePerson(person.id)}
            change={(event) => changeNameHandle(event, person.id)}
          >
            {statement}
          </Person>
        ))}
    </div>
  );
};

export default App;

Summary

Tổng kết day-02 có những topic sau quan trọng cần ghi nhớ nha:

  1. Conditional Rendering
  2. List Rendering

Time to Practice

Các bạn hãy cố gắng tự thực hành những kiến thức trên để quen tay và hiểu hơn nha!