To all aspiring front-end developers out there, learning React for the first time can present some challenges. For instance, imagine you're learning React by creating a Todo application and writing a bit of code every day. To test the app's behaviour, you need a substantial number of todos in your list, so you create them. However, at the end of the day, when you wrap up and shut down your laptop or close the browser, all that data is lost ๐ช.
Now, when you begin working on the app the following day, you must recreate all those todos once more!
One possible solution to this problem is to create a persistent database, such as MongoDB or SQL. However, since you are still learning, you may not want to overcomplicate things just yet.
The useStoredState
hook comes to the rescue ๐.
Just like the useState
hook, our custom useStorageHook
creates a state and returns a setState-like function to change the state. Additionally, it stores the state in either localStorage
or sessionStorage
. When you open the application the next day, it automatically initializes the state with what is stored in the storage. And when you update the state, it gets updated in storage as well.
Pretty neat right?
Here's how you create the useStoredState
custom hook.
import { useState, useEffect } from "react";
function useStoredState(storage, defaultValue, stateKey) {
const storedStateString = storage.getItem(stateKey);
let storedState;
try {
storedState = storedStateString
? JSON.parse(storedStateString)
: defaultValue;
} catch (err) {
storedState = defaultValue;
}
const [state, setState] = useState(storedState);
useEffect(() => {
storage.setItem(stateKey, JSON.stringify(state));
}, [state, stateKey, storage]);
const setStoredState = (value) => {
setState(value);
};
return [state, setStoredState];
}
The first argument this function takes is storage
, which can be either localStorage
or sessionStorage
. The second argument is defaultValue
, which represents the initial value of the state. The third argument is stateKey
, which determines how your state will be stored.
Here's how you use this in a react component:
import "./styles.css";
import Todo from './Todo';
import AddTodoInput from "./AddTodoInput";
export default function Todos() {
const [todos, setTodos] = useStoredState(localStorage, [], "todos");
const onAddToDo = (todoName) => {
setTodos([...todos, {
name: todoName,
}]);
}
const onCheckTodo = todoName => {
setTodos(todos.filter(todo => todo.name !== todoName))
}
return (
<div className="App">
<Todo onCheckTodo={onCheckTodo} />
<AddTodoInput onAddToDo={onAddToDo} />
</div>
);
}
That's it! Your react app now persists data without the need of a server or db connection. Happy coding ๐ค
PS: You can extend this to implement an app-wide stored state as well.
Follow me on twitter to stay in touch. You can find my writings at devshekhawat.com. Also, subscribe to the newsletter here to get daily updates on ๐ป web development, โ๏ธ life and ๐ productivity.