Introduce
Hello everyone, we meet again
In the previous episode in the series, I shared about how to create a SolidJS project and the basic operation of a SolidJS application.
In this episode 3, you and I will learn about Reactivity primitives of SolidJS .
Content
- Signals
- Effects
- Memo
“Reactivity primitives” are a concept in web programming and are part of techniques for handling user interactions on interfaces. It includes basic methods for handling interaction events and updating the interface in real time.
Vd: thao tác nhấn vào một nút trên web là một phương thức tương tác cơ bản và có thể được sử dụng để xử lý sự kiện nhấp chuột hoặc gõ từ bấm phím.
Reactivity primitives – What are Signals?
As one of the fundamental definitions of reactivity primitives in Solid, it represents a state, a value, a function, data or signal that you need to represent in the interface…
when you change the value of signals , it will automatically update to anywhere and anything that is using the value of that signals .
Initialize a signal:
1 2 3 4 | <span class="token keyword">import</span> <span class="token punctuation">{</span> createSignal <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"solid-js"</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> count <span class="token punctuation">,</span> setCount <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">createSignal</span> <span class="token punctuation">(</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Here we can understand the following:
- The
0
argument passed to thecreateSignal()
function is called the initialization value . - The return value is an array of two functions. Use destructuring in Javascript to be able to name these functions. I named the getter function
count
and the setter functionsetCount
. - In the above example, if we want to log the
count
value, it will not work, instead we have to call thecount()
function to get the desired return value.
1 2 3 | console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> count <span class="token punctuation">)</span> <span class="token comment">// không trả về giá trị</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token comment">// 0</span> |
- The
setCount()
function is used to update the return value (count) through thecount()
function.
1 2 3 4 | <span class="token comment">// Chúng ta có 2 cách viết như sau </span> <span class="token function">setCount</span> <span class="token punctuation">(</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token function">setCount</span> <span class="token punctuation">(</span> <span class="token parameter">c</span> <span class="token operator">=></span> c <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">)</span> |
Do you see the same syntax in ReactJS? Comment to let me know if Signals is similar or different from the
useState
function in ReactJS .
Reactivity primitives – What are Effects?
Signals are values that we can monitor and use, but they are only half the story.
Effects execute based on the value of Signals changes. Now Effects creates a side effect
(side effect) that depends on the Signals signal.
1 2 3 4 5 6 | <span class="token keyword">const</span> <span class="token punctuation">[</span> count <span class="token punctuation">,</span> setCount <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">createSignal</span> <span class="token punctuation">(</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">createEffect</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"The count is now"</span> <span class="token punctuation">,</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
I have a small example of counting numbers as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">import</span> <span class="token punctuation">{</span> render <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'solid-js/web'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> createSignal <span class="token punctuation">,</span> createEffect <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'solid-js'</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">Counter</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> count <span class="token punctuation">,</span> setCount <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">createSignal</span> <span class="token punctuation">(</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">createEffect</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"The count is now"</span> <span class="token punctuation">,</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> button</span> <span class="token attr-name">onClick</span> <span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span> <span class="token punctuation">{</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">setCount</span> <span class="token punctuation">(</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span></span> <span class="token punctuation">></span></span><span class="token plain-text"> Click Me </span><span class="token punctuation">{</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> button</span> <span class="token punctuation">></span></span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> <span class="token class-name">Counter</span></span> <span class="token punctuation">/></span></span> <span class="token punctuation">,</span> document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token string">'app'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> |
You can copy the above code and paste it into https://playground.solidjs.com/ to run the video directly, or you can try it right on the source code created in the previous episode ^^
I will explain the above example as follows:
- We have initialized 1 Signals with a value of 0
- Then continue we use the createEffect() function and pass in a function to log (displayed on the
tab Console
) the current count valuecount()
- Next in the interface we have 1 button, when clicked will increase the count to +1 unit
When we use the createEffect() function it will always create a side effect to let us know how the count()
value changes.
Before we click on the Click Me
button, this side effect has been executed and it console.log("The count is now", count())
the initial initial value is 0
.
Then every time we click on the Click Me
button, the count()
value will increase by 1 -> also means a side effect (side effect) console.log("The count is now", count())
You can also use multiple createEffect() functions, each Effect will generate a
side effect
according to each Signal in the same Component <Counter/>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <span class="token keyword">import</span> <span class="token punctuation">{</span> render <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'solid-js/web'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> createSignal <span class="token punctuation">,</span> createEffect <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'solid-js'</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">Counter</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> count <span class="token punctuation">,</span> setCount <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">createSignal</span> <span class="token punctuation">(</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> name <span class="token punctuation">,</span> setName <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">createSignal</span> <span class="token punctuation">(</span> <span class="token string">"Tùng Anh Nguyễn"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">createEffect</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"The count is now"</span> <span class="token punctuation">,</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">createEffect</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"My name is "</span> <span class="token punctuation">,</span> <span class="token function">name</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// Cách update signal gọi trực tiếp hàm getter là count()</span> <span class="token function">setCount</span> <span class="token punctuation">(</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token comment">// Signal chấp nhận 1 hàm sử dụng giá trị trước đó đặt cho giá trị tiếp theo.</span> <span class="token function">setName</span> <span class="token punctuation">(</span> <span class="token parameter">name</span> <span class="token operator">=></span> name <span class="token operator">+</span> <span class="token string">" (Jeremy)"</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> button</span> <span class="token attr-name">onClick</span> <span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span> <span class="token punctuation">{</span> handleClick <span class="token punctuation">}</span></span> <span class="token punctuation">></span></span> <span class="token plain-text">Click Me: </span><span class="token punctuation">{</span> <span class="token function">name</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token plain-text"> - </span><span class="token punctuation">{</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> button</span> <span class="token punctuation">></span></span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> <span class="token class-name">Counter</span></span> <span class="token punctuation">/></span></span> <span class="token punctuation">,</span> document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token string">'app'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> |
Reactivity primitives – What are Memos?
Most of the jobs we come across can use Signals to suffice. However, sometimes we will encounter cases where we have to handle repetitive tasks. So what is the solution?
createMemo
creates a signal (Signal) whose main job is to read and recalculate its value whenever the value changes or updates.
We will use createMemo
when we want to cache some values and access them without considering retrieving them, until a dependency changes.
For example, I want to display the count()
100 times and update the count value when the button is clicked —> using createMemo()
will allow the recalculation to happen only once for every click
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <span class="token keyword">import</span> <span class="token punctuation">{</span> render <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'solid-js/web'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> createSignal <span class="token punctuation">,</span> createMemo <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'solid-js'</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">Counter</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span> count <span class="token punctuation">,</span> setCount <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">createSignal</span> <span class="token punctuation">(</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// Nếu chúng ta không bọc nó trong createMemo</span> <span class="token comment">// Việc tính toán và thể hiện giá trị sẽ xảy ra 100 lần cho mỗi lần click</span> <span class="token comment">// const counter = () => {</span> <span class="token comment">// return count();</span> <span class="token comment">// }</span> <span class="token comment">// Ngược lại nếu chúng ta bọc nó trong createMemo</span> <span class="token comment">// Việc tính toán lại và thể hiện giá trị chỉ xảy ra một lần cho mỗi lần click</span> <span class="token keyword">const</span> counter <span class="token operator">=</span> <span class="token function">createMemo</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> button</span> <span class="token attr-name">onClick</span> <span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span> <span class="token punctuation">{</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">setCount</span> <span class="token punctuation">(</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span></span> <span class="token punctuation">></span></span> <span class="token plain-text">Count: </span><span class="token punctuation">{</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> button</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token punctuation">></span></span> <span class="token plain-text">1. </span><span class="token punctuation">{</span> <span class="token function">counter</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token punctuation">></span></span> <span class="token plain-text">2. </span><span class="token punctuation">{</span> <span class="token function">counter</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token punctuation">></span></span> <span class="token plain-text">3. </span><span class="token punctuation">{</span> <span class="token function">counter</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token punctuation">></span></span> <span class="token plain-text">4. </span><span class="token punctuation">{</span> <span class="token function">counter</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token punctuation">></span></span> <span class="token plain-text">5. </span><span class="token punctuation">{</span> <span class="token function">counter</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> p</span> <span class="token punctuation">></span></span> <span class="token plain-text">95 more times...</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> p</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span></span> <span class="token punctuation">></span></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> <span class="token class-name">Counter</span></span> <span class="token punctuation">/></span></span> <span class="token punctuation">,</span> document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token string">'app'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> |
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token comment">// Nếu chúng ta không bọc nó trong createMemo</span> <span class="token comment">// Việc tính toán và thể hiện giá trị sẽ xảy ra 100 lần cho mỗi lần click</span> <span class="token keyword">const</span> <span class="token function-variable function">counter</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Ngược lại nếu chúng ta bọc nó trong createMemo</span> <span class="token comment">// Việc tính toán lại và thể hiện giá trị chỉ xảy ra một lần cho mỗi lần click</span> <span class="token keyword">const</span> counter <span class="token operator">=</span> <span class="token function">createMemo</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">count</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> |
This is very beneficial for the computation and memory usage of effects, data with dependencies, and above all, it reduces the work that needs to be done for performance-intensive operations such as DOM generation, computation, and so on. value math….
Let’s recap episode 3
In this episode 3 we learned about the main features of Reactivity primitives like Signals , Effects and Memos .
In the next episode, I will go to the next part:
- 🔄 Lifecycle methods
- onMount
- onCleanup
- onError
Thank you for watching episode 3 in the series about SolidJS . If you have any questions or suggestions about the article, please comment to help me, thank you
Reference
https://www.solidjs.com/tutorial/introduction_signals https://www.solidjs.com/tutorial/introduction_effects https://www.solidjs.com/tutorial/introduction_memos