Yesterday, we looked at a mostly vanilla JS way to use Preact for state-based UI.
Today, we're going to look at an easier way to manage state with Signals, since having to reset the value
property can be clunky with arrays and objects.
Let's dig in!
Creating a state store
For this approach, we're going to create a store: an object of functions we can use to modify our state for us.
When we're done, we'll be able to run functions like todos.add()
and todos.remove()
instead of having to manually update todos.value
over and over again.
To start, we'll create an IIFE and assign that to our todos
variable instead of the Signals object.
let todos = (function () { // Our state and functions will live here... })();
Inside it, we'll keep our actually Signal object: the reactive data we use in our app.
// Create a data store let todos = (function () { // The reactive data let state = signal(JSON.parse(localStorage.getItem('todos-preact')) || []); })();
What we're doing here is scoping our state inside the function.
Adding methods
Next, let's add methods to get and modify our state
.
First, we'll include a get()
function that returns the state.value
.
// Reactive todo data let state = signal(JSON.parse(localStorage.getItem('todos-preact')) || []); /** * Get the todo list * @return {Array} the todolist items */ function get () { return state.value; }
Next, we'll include an add()
function. It accepts the todo
item to add as an argument.
We'll copy/paste the code to add a todo into it, and modify the variables to fit our updated code.
/** * Add an item to the todo list * @param {String} todo The item to add */ function add (todo) { state.value = [...state.value, todo]; }
Then, we'll add a remove()
function that accepts the index
of the todo item to remove as an argument.
We'll again copy/paste our code and update variable names.
/** * Remove an item from the todo list * @param {Integer} index The index of the todo list item to remove */ function remove (index) { let arr = [...state.value]; arr.splice(index, 1); state.value = arr; }
Finally, we'll return an object with our three methods.
// Create a data store let todos = (function () { // Reactive todo data let state = signal(JSON.parse(localStorage.getItem('todos-preact')) || []); // ... return {get, add, remove}; })();
When the IIFE runs, it returns an object of functions that have access to the state
object and can modify it for us, but block us from modifying the Signal directly.
Using our store
Now, we can add todos like this…
// Otherwise, add todo todos.add(form.todo.value);
And remove them like this…
// Otherwise, remove the todo todos.remove(index);
Inside our template, we'll use the todos.get()
function to get the array of items instead of todos.value
.
// Otherwise, render the todo items return html` <ul> ${todos.get().map(function (todo, index) { return html`<li>${todo} <button data-delete="${index}">Delete</button></li>`; })} </ul>`;
Using a store results in cleaner, easier-to-read code that's less likely to throw errors.
The Vanilla JS Academy is a project-based online JavaScript workshop for beginners. Click here to learn more.
Cheers,
Chris
Want to share this with others or read it later? View it in a browser.
0 Komentar untuk "[Go Make Things] Easier state management with Preact Signals"