- vừa được xem lúc

Series SolidJS - Tập 5: Control Flow trong SolidJS là gì?

0 0 11

Người đăng: Pate Kem

Theo Viblo Asia

I. Giới thiệu

Hello everyone, chúng ta lại gặp nhau nữa rồi ✌️
Tập trước trong series mình đã chia sẻ về Lifecycle trong SolidJS và các phương thức, cách chúng hoạt động.

Tập này mình và các bạn sẽ cùng nhau tìm hiểu về Control Flow trong SolidJS nhé.

II. Nội dung

🕹️ Control Flow là gì và các thành phần chính:

  • Show
  • For
  • Index
  • Switch
  • Dynamic
  • Portal
  • Error Boundary

1. Control Flow trong SolidJS là gì?

JSX cho phép chúng ta sử dụng JavaScript để handle các logic trong functional component. Nếu không sử dụng Virtual DOM, việc sử dụng tùy ý Array.prototype.map sẽ tạo ra một sự lãng phí lên DOM sau mỗi lần cập nhật.

👉 Giải pháp SolidJS được đưa là bọc chúng lại trong các Component của Control Flow.

2. Show trong Control Flow?

Luồng hoạt động cơ bản nhất chúng ta thường hay gặp là các câu so sánh có điều kiện - conditional statement (if - else - else if) hay toán tử so sánh - conditional operator (a ? b : c), (a && b)... 🤯

SolidJS cung cấp Component <Show /> cho phép chúng ta sử dụng để thay thế các flow so sánh có điều kiện và giúp code trở nên dễ đọc và dễ sử dụng hơn.

import { render } from "solid-js/web";
import { createSignal, Show } from "solid-js"; function App() { const [loggedIn, setLoggedIn] = createSignal(false); const toggle = () => setLoggedIn(!loggedIn()); return ( <> <Show when={loggedIn()} fallback={<button onClick={toggle}>Log in</button>} > <button onClick={toggle}>Log out</button> </Show> </> );
} render(() => <App />, document.getElementById("app"));

Ví dụ trên fallback chỉ hoạt động và hiển thị trên giao diện, khi điều kiện so sánh là 1 boolean signal loggedIn() === false được truyền vào When

Và dĩ nhiên khi loggedIn() === true giao diện sẽ hiển thị <button onClick={toggle}>Log out</button>

3. For trong Control Flow?

Component <For/> trong SolidJS dùng để xử lý việc loop qua một mảng các đối tượng và hiển thị lên giao diện. Khi mảng có sự thay đổi, <For/> cập nhật hoặc di chuyển các item trong DOM thay vì tạo lại chúng. Hãy xem một ví dụ bên dưới.

import { render } from 'solid-js/web';
import { createSignal, For } from 'solid-js'; function App() { const [cats, _setCats] = createSignal([ { id: 'id01', name: 'Pate Kem' }, { id: 'id02', name: 'Naruto' }, { id: 'id03', name: 'Luffy' } ]); return ( <For each={cats()}>{(cat, index) => <li> <span> {index() + 1}: {cat.name} - {cat.id} </span> </li> }</For> );
} render(() => <App />, document.getElementById('app'))

Component <For/> có một property là each để nhận dữ liệu (một mảng các phần tử).

Sau đấy chúng ta sẽ pass trực tiếp một callback function (cũng khá tưởng tự như map callback trong Javascript nhỉ)

Callback trên có đối số đầu tiên là chính là từng phần tử (item) trong mang cats (đặt tên là cat) và đối số thứ hai là i (index - chỉ mục) thể hiện thứ tự của từng phần tử trong mảng.

Lưu ý rằng đối số index chỉ là một signal, không phải là một hằng số. Mỗi node được hiển thị sẽ được ghép cặp với từng phần tử trong mảng.
Nếu thay đổi vị trí phần tử trong mảng, thay vì bị hủy và tạo lại thì các node sẽ thay đổi và đánh chỉ mục (index) tương ứng.

4. Index trong Control Flow?

Component <Index/> cũng giúp cho chúng ta render một list data, nhưng khác với <For/> ở chỗ khi render bằng <Index/> sẽ hạn chế số lần re-render hơn so với <For/> (tùy thuộc hoàn cảnh...)

Về mặt syntax (cú pháp) thì gần như tương tự với For

<Index each={cats()}>{(cat, index) => <li> <span> {index() + 1}: {cat.name} - {cat.id} </span> </li>
}</Index>

Trong Javascript khi làm việc với giá trị nguyên thủy (primitivies value như string hay number) chúng sẽ luôn được so sánh theo giá trị.

Khi sử dụng <For/> với các giá trị nguyên thủy hoặc mảng lồng mảng (array of arrays) chúng sẽ gây việc re-render không cần thiết bởi vì <For/> quan tâm tới vị trí thay đổi của từng đối tượng, còn <Index/> thì không.

Vd: khi ta ánh xạ 1 list string value xuống các thẻ <input/>, khi update giá trị của input trong list đấy sẽ khiến cho <input/> đấy bị tạo lại (re-render) 😫

👉 Do đó <Index/> được cung cấp để giải quyết cho trường hợp trên vì <Index/> chỉ quan tâm đến sử thay đổi giá trị trên từng phần từ (item)

Hiểu đơn giản là khi làm việc với một mảng các đối tượng (Array Object) thì hãy sử dụng <For/> và ngược lại khi làm việc với các giá trị nguyên thủy (string, number, boolean...) hãy sử dụng <Index/> nhé.

import { render } from "solid-js/web";
import { createSignal, For, Index } from "solid-js"; function App() { const [cats, setCats] = createSignal([ "Jim", "Maru", "Henry", ]); setTimeout( () => setCats(["Maru", "Jim", "Jim", "New Cat"]), 2000 ); return ( <ul> <For each={cats()}> {(name, index) => { console.log(`For: rendered ${name}`); return ( <li> <span> {index()}: {name} </span> </li> ); }} </For> </ul> );
} render(() => <App />, document.getElementById("app"));

Trước khi update signal cats

Sau khi update signal cats


Sử dụng <Index/> thay cho <For/>

<For each={cats()}> {(name, index) => { console.log(`For: rendered ${name()}`); return ( <li> <span> {index()}: {name()} </span> </li> ); }}
</For>

Trước khi update signal cats

Sau khi update signal cats

5. Switch trong Control Flow?

Như ở trên mình đã giới thiệu <Show/> cho các case so sánh điểu kiện để hiển thị giao diện theo mong muốn.

Nhưng đôi khi chúng ta muốn xử lý các điều kiện có nhiều hơn 2 kết quả, ở trường hợp này chúng ta nên sử dụng <Switch/> và <Match/> (liên tưởng ngay switch/case nhỉ các bạn 😂)

<Switch fallback={<p>{x()} is between 5 and 10</p>}> <Match when={x() > 10}> <p>{x()} is greater than 10</p> </Match> <Match when={5 > x()}> <p>{x()} is less than 5</p> </Match>
</Switch>

Nếu không match bất kì điều kiện nào thì sẽ render fallback

6. Dynamic trong Control Flow?

<Dynamic/> hữu ích khi bạn cần render từ một tập dữ liệu có sẵn.

import { render, Dynamic } from "solid-js/web";
import { For } from "solid-js"; function App() { const hTags = { 1: "Heading 1", 3: "Heading 3", 5: "Heading 5", }; return ( <> <For each={Object.entries(hTags)}> {([key, value]) => <Dynamic component={`h${key}`}>{value}</Dynamic>} </For> </> );
} render(() => <App />, document.getElementById("app"));

7. Portal trong Control Flow?

Đôi khi việc xây dựng các element bên ngoài giao diện gốc của ứng dụng sẽ có lợi về mặt xử lý style, logic hơn là dùng z-index. Chẳng hạn như việc tạo giao diện Popup Modal hay Tooltip...<Portal/> thường được dùng để tạo

import { render, Portal } from "solid-js/web";
import "./styles.css"; function App() { return ( <div> <h2>Pate Kem.</h2> <Portal> <div class="popup"> <h1>Popup</h1> <p>Some text you might need for something or other.</p> </div> </Portal> </div> );
} render(() => <App />, document.getElementById("app"));

file styles.css

.popup { background: brown; padding: 1rem; min-height: 200px; min-width: 200px;
}

Cùng cấp với giao diện gốc <div id="app">...</div> của ứng dụng.

Portal cho phép tạo một thẻ <div/>, chứa nội dung mà chúng ta thiết lập và xuất hiện bên trong document.body

8. Error Boundary trong Control Flow?

import { createSignal, createEffect, onCleanup, ErrorBoundary } from "solid-js";
import { render } from "solid-js/web"; function Counter() { const [count, setCount] = createSignal(0); const id = setInterval(() => { setCount(count() + 1); }, 1000); onCleanup(() => clearInterval(id)); createEffect(() => { if (count() >= 5) { throw new Error("Count is too high!"); } }); return <div>{count()}</div>;
} function App() { return ( <ErrorBoundary fallback={<div>Something went wrong!</div>}> <Counter /> </ErrorBoundary> );
} render(() => <App />, document.getElementById("app"));

Trong đoạn code trên, Component <Counter/> sử dụng createEffect để kiểm tra giá trị của count, và nếu count() >= 5 thì sẽ throw ra lỗi.

Trong <App/>, Component <Counter/> được bọc bởi một ErrorBoundary để hiển thị fallback khi có lỗi xảy ra.

III. Tổng kết tập 5

Tập này chúng ta đã cùng tìm hiểu về khái niệm và các thành phần của Control FLow trong SolidJS.

Trong tập sau mình sẽ đi vào phần 🚚 Bindings trong SolidJS nhé:

  • Events
  • Style
  • ClassList
  • Refs
  • Forwarding Refs
  • Spreads
  • Directives

Cảm ơn các bạn đã theo dõi tập 5 trong series về SolidJS. Nếu các bạn có thắc mắc hoặc góp ý về bài viết hãy comment giúp mình nhé, cảm ơn các bạn 😘

Tham khảo

https://www.solidjs.com/tutorial/flow_show
https://youtu.be/hdUwDmprSmg

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 500

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 414

- vừa được xem lúc

Một số phương thức với object trong Javascript

Trong Javascript có hỗ trợ các loại dữ liệu cơ bản là giống với hầu hết những ngôn ngữ lập trình khác. Bài viết này mình sẽ giới thiệu về Object và một số phương thức thường dùng với nó.

0 0 136

- vừa được xem lúc

Tìm hiểu về thư viện axios

Giới thiệu. Axios là gì? Axios là một thư viện HTTP Client dựa trên Promise.

0 0 117

- vừa được xem lúc

Imports và Exports trong JavaScript ES6

. Giới thiệu. ES6 cung cấp cho chúng ta import (nhập), export (xuất) các functions, biến từ module này sang module khác và sử dụng nó trong các file khác.

0 0 93

- vừa được xem lúc

Bài toán đọc số thành chữ (phần 2) - Hoàn chỉnh chương trình dưới 100 dòng code

Tiếp tục bài viết còn dang dở ở phần trước Phân tích bài toán đọc số thành chữ (phần 1) - Phân tích đề và những mảnh ghép đầu tiên. Bạn nào chưa đọc thì có thể xem ở link trên trước nhé.

0 0 229