State Management in React With Valtio
State management for React is an important issue, and it can be challenging to decide which of the libraries to use since there are the correct times and places to apply each. Valtio offers a simple, performant, and flexible solution that is well-suited to many projects, and this article will tell you all about it.
One tool used for state management is Valtio, which uses proxies to provide a mutation-style API. Proxy
classes serve as an interface to another object. In its broadest sense, a proxy “wraps” the object, and to access the object, one has to pass through the proxy so, the proxy can do additional operations before returning the object. We can proxy almost anything. In the following sections, we’ll show how to use Valtio with React, and you’ll see it’s an easy way of working.
Why Choose Valtio as a state manager in React
Valtio is a lightweight and intuitive state management library for React that offers several benefits over other state managers, including:
- Minimalistic API: Valtio has a simple and easy-to-learn API, making it less cumbersome than other state managers.
- Reactive updates: Valtio uses Proxies to create reactive updates, meaning that state changes are reflected automatically in the UI.
- Performance: Valtio has a small footprint and is highly performant, making it an ideal choice for projects that require high performance.
- Server-side rendering support: Valtio has built-in support for server-side rendering, which means that your app will smoothly work whether running on the client or the server.
- Flexible data structures: Valtio supports flexible data structures, such as maps and sets, making it easier to work with complex data.
- Easy integration: Valtio can easily integrate with other libraries and tools, like React and TypeScript.
Getting Started
We will start by creating a new React application.
npx create-react-app simple-state-with-valtio
Next, we install Valtio.
yarn add valtio
Then we import the proxy
and useProxy
functions from Valtio into our app.
import { proxy, useProxy } from "valtio";
Our React component uses the useProxy
function to create a local snapshot that tracks changes while the proxy
function creates a new proxy state.
Components State
Components are a user interface’s building blocks that encapsulate a UI logic and can be reused throughout an application. A component can represent a small UI element like a button or a more complex UI element like a form or a modal. They are JavaScript functions or classes that return a React element, which describes what should be rendered on the screen (React element is a lightweight description of what to render, consisting of a type, props, and children)
Valtio has to be a part of the React lifecycle to segregate component states for reuse. You can wrap a proxy in a ref, passing it with props or context. We will discuss how to do this in the outline that follows.
Here is a demonstration of how Valtio lives in the component state:
import { proxy, useSnapshot } from "valtio";
/** use context to pass password state */
const PasswordButtonContext = React.createContext(undefined);
const PasswordGeneratorStateProvider = ({
children,
numbers,
length,
symbols,
}) => {
const state = React.useRef(
proxy(new PasswordState({ numbers, length, symbols }))
).current;
return (
<PasswordButtonContext.Provider value={state}>
{children}
</PasswordButtonContext.Provider>
);
};
// wrap in a custom hook for ease of use
function usePasswordGeneratorState() {
const passwordState = React.useContext(PasswordButtonContext);
const snapshot = useSnapshot<PasswordState>(passwordState);
return { passwordState, snapshot };
}
export default App;
OUTPUT
We created a PasswordButtonContext
using the React.createContext
function. This context then provides the state of the password generator using the PasswordGeneratorStateProvider
component. Finally, the usePasswordGeneratorState
hook lets us access the password generator state and its snapshot. Here is the link to the complete code on GitHub.
Note useRef
is a React hook that allows us to create a mutable variable that persists between renders of a component. It returns an object with a single property, current
, that holds the current value of the reference. It is used when we need to modify a value without causing a re-render of the component.
useContext
is a React hook that allows you to access data and functions from a parent component’s context object. It is often used to simplify data management and make data sharing between components more efficient.
A full explanation of the features of Valtio to use in manipulation states is discussed below.
Session Replay for Developers
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — an open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.
Proxy and useProxy
In the components state, the proxy
tracks change to the original object and all nested objects, notifying listeners when an object is modified.
import { proxy } from 'valtio'
const state = proxy({ count: 0, text: 'hello' })
The useProxy
is a hook provided by the Valtio library that allows you to create a reactive binding to a Valtio proxy object in your React components, making it easy to read and update the state in a performant and scalable way.
When useProxy
is used with a Valtio proxy object, it returns a reactive state object that automatically updates when the original proxy
object changes. This functionality shows you can use the returned state
object to read the current state of the proxy object, and any changes you make to the state
object will automatically reflect in the UI.
Here’s an example of how you can use useProxy
with a Valtio proxy
object:
import { proxy, useProxy } from "valtio";
const state = proxy({
count: 0,
text: "",
});
function Counter() {
const proxyState = useProxy(state);
return (
<div>
<p>Count: {proxyState.count}</p>
<button onClick={() => ++state.count}>Increment</button>
</div>
);
}
export default function App() {
return (
<>
<Counter />
</>
);
}
In this example, we define a Valtio proxy object called state
with a count
and a text
property. We then use the useProxy
hook to create a reactive binding to the state
object, which we store in the proxyState
variable. Finally, we use the proxyState
object to display the current count value in the UI and to update the count value when the button is clicked.
Using useProxy
, we can create a reactive binding to the state
object that ensures that our UI is always up-to-date with the latest state values and that changes to the state are always reflected in the UI.
Snapshot and useSnapshot
One of the critical features of Valtio is the snapshot
and useSnapshot
functions.
The snapshot
function creates a read-only copy of your state in the component. It is useful when you want to pass the current state of your application to a component or a function without allowing it to modify the state directly. The snapshot
function returns a plain JavaScript object that represents the current state of your application.
Here is an example of using snapshot
in Valtio:
import { proxy, snapshot } from "valtio";
const state = proxy({
count: 0,
});
console.log(snapshot(state)); // { count: 0 }
The useSnapshot
function creates a React hook that allows you to access the current state of your application in a component. It is similar to the useContext
hook but only updates the component when the state depends on changes.
Here is an example of using useSnapshot
in Valtio
import React from "react";
import { proxy, useSnapshot } from "valtio";
const state = proxy({
count: 0,
});
function Counter() {
const snap = useSnapshot(state);
return (
<div>
{snap.count}
<button onClick={() => ++state.count}>+1</button>
</div>
);
}
export default function App() {
return (
<>
<Counter />
</>
);
}
In this example, the useSnapshot
hook returns a read-only snapshot of the state, which is used to render the count
component. The state object is updated when the increment
button clicks, triggering a counter
component re-render.
Conclusion
A typical modern app requires state info management, making Valtio a powerful tool since it is straightforward and robust. Moreover, it combines the potential of proxies in React.js and JavaScript to simplify and modify state data. Here is a GitHub repository for managing states in Valtio. You can also check the Valtio documentary for other related API lean to the library.