Getting Started with HookState Library
React.js is a mature JavaScript library for declarative and dynamic user interfaces. React.js breaks the UI into components. The concept of state is critical in React.js programming. <!--more--> We need to know what a state is, how to maintain it efficiently, and how to deal with increasing complexity as the application expands.
In this article, we will learn the basics of state management in React.js using the Hookstate library.
Table of contents
- Pre-requisites
- Understanding state management
- Why use state management libraries?
- Application setup
- Create the global state
- Create
AddTodo
component - The
TodoList
component - The
App.js
component - Demo
- Conclusion
- Further reading
Pre-requisites
As a pre-requisite, the reader must have the following:
- A web browser such as Google Chrome.
- A code editor such as VS Code or any preferred IDE.
- Knowledge of the JavaScript programming language.
- Basics of the React library.
- Have a Node.js LTS or later version on your development environment.
Understanding state management
In a nutshell, state management is a pattern in which we control the communication and sharing of data across the reusable components of the modern frontend frameworks.
Our application encapsulates data in a data structure that reflects the logical state of the application that we can use to access and change to transition between various states.
The status of the application ("state") changes as a result of the user's actions.
A case study can be an e-commerce application. For example, an e-commerce website can have components such as Button
, Cart
, Checkout
, Login
, and many more.
When a user adds an item to the Cart
component or performs a successful login, these actions will alter the state of our component and hence the entire application.
Why use state management libraries?
In modern frontend applications, we break the UI into logical reusable components. These components often need dynamic data to share and pass around.
In an extensive application, keeping track of the global state while avoiding prop
drilling can be difficult. That is where state management libraries come in.
Unlike redux which uses reducers, dispatch, and actions that can sometimes be confusing, the Hookstate library takes the concept of state in React to a new level.
The Hookstate library wraps the idea of the declarative React useState
to a global version and extends it with extra features.
Some of its core features include:
- A plugin system to persist and state validate to extend the library features.
- Hookstate's standard TypeScript support for state management.
- Support for asynchronous and partial state updates in deeply nested components and more.
Application setup
To scaffold a new React application, we will use a new frontend build tool, Vite.
Vite optimizes the build process for developers by bundling the pre-configured code using Rollup rather than Webpack.
To start a Vite app with a basic React template, type the following command:
npm init vite@latest hookstate-demo -- --template react
Next, navigate inside the hookstate-demo
folder on the terminal and execute the npm install
command:
npm install
Next, add the hookstate
and uuid
packages to the project as shown:
npm install --save @hookstate/core uuid
Lastly, spin up a development server on your browser by running the command:
npm run dev
If we switch to our browser and access the URL http://localhost:3000/
, we should see something similar to this:
Create the global state
To create and manage a global state, add a folder in your src
directory and name it states
.
Now, we'll create a TaskState.js
file under the states
folder containing a custom hook. Our function will invoke Hookstate's method createState([])
to create a new state and return it.
Import the uuid
and the @hookstate/core
package to create a global state.
import { createState, useState } from "@hookstate/core";
import {v4 as uuid} from "uuid";
Note: The
useState
hook resembles React's built-in hook. When accessing hooks simultaneously in a single file, an alias is helpful to eliminate ambiguity.
Below the library import, instantiate the createState
to create a new state.
// Initial state - empty array.
const taskState = createState([]);
Lastly, let's create a custom hook to reuse when manipulating the state in our components. Create and export the useTaskState
function:
export function useTaskState() {
}
Inside the function body, add the state
variable to initiate the state from the useState
:
// assign state
const state = useState(taskState);
Finally, return the following functions:
return {
// addTask method takes the new state and returns a new state using the .set(method)
addTask(newTask) {
return state.set((tasks) => [...tasks, { newTask, id: uuid() }]);
},
// filter task lists to remove a list item
removeTask(id) {
return state.set((tasks) => tasks.filter((task) => task.id !== id));
},
// state.get() retieves the Todo list state
get getTasks() {
return state.get();
}
};
Let's briefly dissect the above code snippet:
- The
addTask
method accepts anewTask
parameter that represents the user value in the input field. Finally, the function returnsstate.get
from Hookstate to perform mutations and add a new task. getTasks
method will access the global store by returning thestate. get
method that works the same as React's in-builtsetState
hook.- Finally, the
removeTask
method accesses the global state and filters out the task by ID.
Create AddTodo component
The AddTodo
component handles the user input to render a new to-do item. Define the AddTodo.jsx
file inside the components
folder.
Our component will reuse the previous custom useTaskState
to access the global state:
import { useTaskState } from "../states/TaskState";
Inside our return statement, we add an input form that accepts a new to-do item. When a user submits the form, we invoke the onSubmit
event handler to add the new item.
Create the AddTodo
function as shown below:
const AddTodo = () => {
const taskState = useTaskState();
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
// trim white spaces
if (!e.target["toDo"].value.trim()) {
return;
}
// add new to-do item
taskState.addTask(e.target["toDo"].value);
e.target["toDo"].value = "";
}}
>
{/*An input element and a button */}
<input name="toDo" />
<button type="submit">Add Todo</button>
</form>
</div>
);
};
Finally, export our function by default:
export default AddTodo;
The TodoList component
The TodoList
component contains our todo
items. Inside your components
folder, add the TodoList.jsx
file with the code below:
import { useTaskState } from "../states/TaskState";
const ToDoList = () => {
const taskState = useTaskState();
const state = taskState.getTasks;
return (
<ul>
{state.length > 0 &&
state.map((todo) => (
<li key={todo.id}>
<span>{todo.text}</span>
{/*Add a delete button*/}
<button onClick={() => taskState.removeTask(todo.id)}>
Delete
</button>
</li>
))}
</ul>
);
};
export default ToDoList;
In the above code, we do the following:
- First, we import the
useState
custom hook from ourstates
folder. const state = taskState.getTasks;
is the variable to access our state.- Inside the JSX, we return an
<ul>
element with lists of available tasks by looping over them.
The App.js component
Our main App.js
file is quite minimal. All we need to add is the ToDoList
component, AddTodo
component, and useTaskState
.
import { useTaskState } from "./states/TaskState";
import ToDoList from "./components/ToDoList";
import AddTodo from "./components/AddTodo";
Finally, export the App
component with the components mapped to the JSX.
export default function App() {
const taskState = useTaskState();
return (
<div className="App">
<h1>TODO APP</h1>
<AddTodo />
<ToDoList />
</div>
);
}
Demo
To run the program, spin up a development server on your terminal with the command:
npm run dev
If we head back to our browser at http://localhost:3000/
, our final app should look similar to this:
Conclusion
This tutorial introduced you to state management in React with Hookstate. To generate the global state and access the state store, we built a Todo app that uses the library's APIs.
You can find the project source code on GitHub.
Happy coding!
Further reading
Peer Review Contributions by: Srishilesh P S