Kết xuất có điều kiện
Các component của bạn thường cần hiển thị những thứ khác nhau tùy thuộc vào các điều kiện khác nhau. Trong React, bạn có thể kết xuất JSX có điều kiện bằng cú pháp JavaScript như câu lệnh if
, &&
và toán tử ? :
.
Bạn sẽ được học
- Cách trả về JSX khác nhau tùy thuộc vào một điều kiện
- Cách bao gồm hoặc loại trừ một phần JSX có điều kiện
- Các phím tắt cú pháp có điều kiện phổ biến mà bạn sẽ gặp trong các codebase React
Kết xuất JSX có điều kiện
Giả sử bạn có một component PackingList
kết xuất một số Item
, có thể được đánh dấu là đã đóng gói hoặc chưa:
function Item({ name, isPacked }) { return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Danh sách đóng gói của Sally Ride</h1> <ul> <Item isPacked={true} name="Bộ đồ vũ trụ" /> <Item isPacked={true} name="Mũ bảo hiểm với một chiếc lá vàng" /> <Item isPacked={false} name="Ảnh của Tam" /> </ul> </section> ); }
Lưu ý rằng một số component Item
có prop isPacked
được đặt thành true
thay vì false
. Bạn muốn thêm dấu kiểm (✅) vào các mục đã đóng gói nếu isPacked={true}
.
Bạn có thể viết điều này dưới dạng câu lệnh if
/else
như sau:
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
Nếu prop isPacked
là true
, đoạn code này trả về một cây JSX khác. Với thay đổi này, một số mục sẽ có dấu kiểm ở cuối:
function Item({ name, isPacked }) { if (isPacked) { return <li className="item">{name} ✅</li>; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Danh sách đóng gói của Sally Ride</h1> <ul> <Item isPacked={true} name="Bộ đồ vũ trụ" /> <Item isPacked={true} name="Mũ bảo hiểm với một chiếc lá vàng" /> <Item isPacked={false} name="Ảnh của Tam" /> </ul> </section> ); }
Hãy thử chỉnh sửa những gì được trả về trong mỗi trường hợp và xem kết quả thay đổi như thế nào!
Lưu ý cách bạn đang tạo logic phân nhánh với các câu lệnh if
và return
của JavaScript. Trong React, luồng điều khiển (như điều kiện) được xử lý bởi JavaScript.
Kết xuất có điều kiện không có gì với null
Trong một số trường hợp, bạn sẽ không muốn kết xuất bất cứ thứ gì. Ví dụ: giả sử bạn không muốn hiển thị các mục đã đóng gói. Một component phải trả về một cái gì đó. Trong trường hợp này, bạn có thể trả về null
:
if (isPacked) {
return null;
}
return <li className="item">{name}</li>;
Nếu isPacked
là true, component sẽ không trả về gì, null
. Nếu không, nó sẽ trả về JSX để kết xuất.
function Item({ name, isPacked }) { if (isPacked) { return null; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Danh sách đóng gói của Sally Ride</h1> <ul> <Item isPacked={true} name="Bộ đồ vũ trụ" /> <Item isPacked={true} name="Mũ bảo hiểm với một chiếc lá vàng" /> <Item isPacked={false} name="Ảnh của Tam" /> </ul> </section> ); }
Trong thực tế, việc trả về null
từ một component không phổ biến vì nó có thể gây bất ngờ cho một developer đang cố gắng kết xuất nó. Thông thường, bạn sẽ bao gồm hoặc loại trừ component một cách có điều kiện trong JSX của component cha. Đây là cách thực hiện!
Bao gồm JSX có điều kiện
Trong ví dụ trước, bạn đã kiểm soát cây JSX nào (nếu có!) sẽ được trả về bởi component. Bạn có thể đã nhận thấy một số trùng lặp trong đầu ra kết xuất:
<li className="item">{name} ✅</li>
rất giống với
<li className="item">{name}</li>
Cả hai nhánh có điều kiện đều trả về <li className="item">...</li>
:
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
Mặc dù sự trùng lặp này không có hại, nhưng nó có thể khiến code của bạn khó bảo trì hơn. Điều gì sẽ xảy ra nếu bạn muốn thay đổi className
? Bạn sẽ phải thực hiện nó ở hai nơi trong code của bạn! Trong một tình huống như vậy, bạn có thể bao gồm một chút JSX có điều kiện để làm cho code của bạn DRY hơn.
Toán tử điều kiện (bậc ba) (? :
)
JavaScript có một cú pháp ngắn gọn để viết một biểu thức điều kiện — toán tử điều kiện hoặc “toán tử bậc ba”.
Thay vì thế này:
if (isPacked) {
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;
Bạn có thể viết thế này:
return (
<li className="item">
{isPacked ? name + ' ✅' : name}
</li>
);
Bạn có thể đọc nó là “nếu isPacked
là true, thì (?
) kết xuất name + ' ✅'
, nếu không (:
) kết xuất name
”.
Tìm hiểu sâu
Nếu bạn đến từ nền tảng lập trình hướng đối tượng, bạn có thể cho rằng hai ví dụ trên hơi khác nhau vì một trong số chúng có thể tạo ra hai “thể hiện” khác nhau của <li>
. Nhưng các phần tử JSX không phải là “thể hiện” vì chúng không giữ bất kỳ trạng thái bên trong nào và không phải là các nút DOM thực. Chúng là các mô tả nhẹ, giống như bản thiết kế. Vì vậy, hai ví dụ này, trên thực tế, hoàn toàn tương đương. Bảo toàn và Đặt lại Trạng thái đi vào chi tiết về cách thức hoạt động của điều này.
Bây giờ, giả sử bạn muốn bọc văn bản của mục đã hoàn thành vào một thẻ HTML khác, chẳng hạn như <del>
để gạch bỏ nó. Bạn có thể thêm nhiều dòng mới và dấu ngoặc đơn hơn để dễ dàng lồng thêm JSX vào mỗi trường hợp:
function Item({ name, isPacked }) { return ( <li className="item"> {isPacked ? ( <del> {name + ' ✅'} </del> ) : ( name )} </li> ); } export default function PackingList() { return ( <section> <h1>Danh sách đóng gói của Sally Ride</h1> <ul> <Item isPacked={true} name="Bộ đồ vũ trụ" /> <Item isPacked={true} name="Mũ bảo hiểm với một chiếc lá vàng" /> <Item isPacked={false} name="Ảnh của Tam" /> </ul> </section> ); }
Kiểu này hoạt động tốt cho các điều kiện đơn giản, nhưng hãy sử dụng nó một cách điều độ. Nếu các component của bạn trở nên lộn xộn với quá nhiều đánh dấu có điều kiện lồng nhau, hãy cân nhắc trích xuất các component con để làm cho mọi thứ gọn gàng hơn. Trong React, đánh dấu là một phần của code của bạn, vì vậy bạn có thể sử dụng các công cụ như biến và hàm để sắp xếp các biểu thức phức tạp.
Toán tử AND logic (&&
)
Một phím tắt phổ biến khác mà bạn sẽ gặp là toán tử AND logic (&&
) của JavaScript. Bên trong các component React, nó thường xuất hiện khi bạn muốn kết xuất một số JSX khi điều kiện là true, hoặc không kết xuất gì nếu không. Với &&
, bạn có thể kết xuất dấu kiểm một cách có điều kiện chỉ khi isPacked
là true
:
return (
<li className="item">
{name} {isPacked && '✅'}
</li>
);
Bạn có thể đọc điều này là “nếu isPacked
, thì (&&
) kết xuất dấu kiểm, nếu không, không kết xuất gì”.
Đây là cách nó hoạt động:
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✅'} </li> ); } export default function PackingList() { return ( <section> <h1>Danh sách đóng gói của Sally Ride</h1> <ul> <Item isPacked={true} name="Bộ đồ vũ trụ" /> <Item isPacked={true} name="Mũ bảo hiểm với một chiếc lá vàng" /> <Item isPacked={false} name="Ảnh của Tam" /> </ul> </section> ); }
Một biểu thức && JavaScript trả về giá trị của phía bên phải của nó (trong trường hợp của chúng ta, dấu kiểm) nếu phía bên trái (điều kiện của chúng ta) là true
. Nhưng nếu điều kiện là false
, toàn bộ biểu thức sẽ trở thành false
. React coi false
là một “lỗ hổng” trong cây JSX, giống như null
hoặc undefined
, và không kết xuất bất cứ thứ gì ở vị trí của nó.
Gán JSX có điều kiện cho một biến
Khi các phím tắt cản trở việc viết code đơn giản, hãy thử sử dụng câu lệnh if
và một biến. Bạn có thể gán lại các biến được xác định bằng let
, vì vậy hãy bắt đầu bằng cách cung cấp nội dung mặc định bạn muốn hiển thị, tên:
let itemContent = name;
Sử dụng câu lệnh if
để gán lại một biểu thức JSX cho itemContent
nếu isPacked
là true
:
if (isPacked) {
itemContent = name + " ✅";
}
Dấu ngoặc nhọn mở “cửa sổ vào JavaScript”. Nhúng biến với dấu ngoặc nhọn trong cây JSX được trả về, lồng biểu thức đã tính trước đó bên trong JSX:
<li className="item">
{itemContent}
</li>
Kiểu này là dài dòng nhất, nhưng nó cũng linh hoạt nhất. Đây là cách nó hoạt động:
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = name + " ✅"; } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Danh sách đóng gói của Sally Ride</h1> <ul> <Item isPacked={true} name="Bộ đồ vũ trụ" /> <Item isPacked={true} name="Mũ bảo hiểm với một chiếc lá vàng" /> <Item isPacked={false} name="Ảnh của Tam" /> </ul> </section> ); }
Giống như trước đây, điều này không chỉ hoạt động cho văn bản mà còn cho cả JSX tùy ý:
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = ( <del> {name + " ✅"} </del> ); } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Danh sách đóng gói của Sally Ride</h1> <ul> <Item isPacked={true} name="Bộ đồ vũ trụ" /> <Item isPacked={true} name="Mũ bảo hiểm với một chiếc lá vàng" /> <Item isPacked={false} name="Ảnh của Tam" /> </ul> </section> ); }
Nếu bạn không quen thuộc với JavaScript, sự đa dạng của các kiểu này có thể gây choáng ngợp lúc đầu. Tuy nhiên, việc học chúng sẽ giúp bạn đọc và viết bất kỳ code JavaScript nào — và không chỉ các component React! Hãy chọn một kiểu bạn thích để bắt đầu, và sau đó tham khảo lại tài liệu này nếu bạn quên cách các kiểu khác hoạt động.
Tóm tắt
- Trong React, bạn kiểm soát logic phân nhánh bằng JavaScript.
- Bạn có thể trả về một biểu thức JSX có điều kiện bằng câu lệnh
if
. - Bạn có thể lưu một số JSX vào một biến có điều kiện và sau đó bao gồm nó bên trong JSX khác bằng cách sử dụng dấu ngoặc nhọn.
- Trong JSX,
{cond ? <A /> : <B />}
có nghĩa là “nếucond
, kết xuất<A />
, nếu không<B />
”. - Trong JSX,
{cond && <A />}
có nghĩa là “nếucond
, kết xuất<A />
, nếu không không có gì”. - Các phím tắt là phổ biến, nhưng bạn không cần phải sử dụng chúng nếu bạn thích
if
đơn giản.
Challenge 1 of 3: Hiển thị một biểu tượng cho các mục chưa hoàn thành với ? :
Sử dụng toán tử điều kiện (cond ? a : b
) để kết xuất một ❌ nếu isPacked
không phải là true
.
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✅'} </li> ); } export default function PackingList() { return ( <section> <h1>Danh sách đóng gói của Sally Ride</h1> <ul> <Item isPacked={true} name="Bộ đồ vũ trụ" /> <Item isPacked={true} name="Mũ bảo hiểm với một chiếc lá vàng" /> <Item isPacked={false} name="Ảnh của Tam" /> </ul> </section> ); }