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()
và 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:
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!