React useSyncExternalStore Hook
Last Updated :
11 Mar, 2024
State management is a critical aspect of React applications, and often, developers need to synchronize their application state with an external data store. React’s useSyncExternalStore hook provides a seamless solution to this challenge.
In this article, we’ll explore what the useSyncExternalStore hook is, its benefits, syntax, and internal workings, and provide practical examples of its usage.
What is useSyncExternalStore?
The useSyncExternalStore hook is a custom React hook that facilitates the synchronization of the React component state with an external data store, such as localStorage or sessionStorage. It allows developers to persist and retrieve component state across browser sessions, enabling seamless user experiences and preserving application state.
Syntax of useSyncExternalStore Hook:
const [state, setState] = useSyncExternalStore(key, initialValue);
- key: A unique identifier used to store and retrieve the state from the external data store.
- initialValue: The initial value of the state.
Reasons to Use useSyncExternalStore:
- Persistent State: By synchronizing the state with an external store, developers can ensure that the application state persists even after the browser is refreshed or the user navigates away from the page.
- Cross-Tab Communication: useSyncExternalStore enables communication between multiple browser tabs or windows by sharing the same state across different instances of the application.
- Seamless User Experience: With a synchronized state, users can seamlessly resume their interactions with the application without losing their previous state.
Internal Working of useSyncExternalStore Hook:
The useSyncExternalStore hook leverages the useState and useEffect hooks internally to manage state and synchronize it with the external data store. When the component mounts, it retrieves the state from the store using the specified key. Any updates to the state trigger the useEffect hook, which updates the state in the external store.
Steps to Create React Application:
Step 1: Create the React application using the following command.
npx create-react-app useSyncExternalStore
cd useSyncExternalStore
Step 2: To start the application run the following command.
npm start
Folder Structure:
The updated dependencies in package.json file will look like:
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}
Example of useSyncExternalStore Hook
Example 1: Counter with Persistent State
Javascript
import React from 'react' ;
import useSyncExternalStore
from './useSyncExternalStore' ;
function Counter() {
const [count, setCount] =
useSyncExternalStore( 'count' , 0);
const increment = () => {
setCount(prevCount => prevCount + 1);
};
const decrement = () => {
setCount(prevCount => prevCount - 1);
};
return (
<div>
<button onClick={decrement}>-</button>
<span>{count}</span>
<button onClick={increment}>+</button>
</div>
);
}
export default Counter;
|
Javascript
import {
useState,
useEffect
} from 'react' ;
function useSyncExternalStore(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
});
useEffect(() => {
window.localStorage
.setItem(key, JSON.stringify(storedValue));
}, [key, storedValue]);
return [storedValue, setStoredValue];
}
export default useSyncExternalStore;
|
Output: Even after refreshing the count didn’t went back to 0.
Example 2: Form Input with Persistent State:
CSS
.form-container {
max-width : 400px ;
margin : 30px 100px ;
}
.input-field {
width : 100% ;
padding : 8px ;
margin-bottom : 10px ;
border : 1px solid #ccc ;
border-radius: 4px ;
box-sizing: border-box;
}
.submit-button {
background-color : #4CAF50 ;
color : white ;
padding : 10px 20px ;
border : none ;
border-radius: 4px ;
cursor : pointer ;
}
.submit-button:hover {
background-color : #45a049 ;
}
|
Javascript
import React from 'react' ;
import useSyncExternalStore
from './useSyncExternalStore' ;
import './App.css' ;
function App() {
const [formData, setFormData] =
useSyncExternalStore( 'form_data' , {
name: '' ,
email: '' ,
message: ''
});
const handleChange = event => {
const { name, value } = event.target;
setFormData(prevData => ({
...prevData,
[name]: value
}));
};
const handleSubmit = event => {
event.preventDefault();
console.log( 'Form submitted:' , formData);
};
return (
<form onSubmit={handleSubmit}
className= "form-container" >
<label>
Name:
<input
type= "text"
name= "name"
value={formData.name}
onChange={handleChange}
className= "input-field"
/>
</label>
<br />
<label>
Email:
<input
type= "email"
name= "email"
value={formData.email}
onChange={handleChange}
className= "input-field"
/>
</label>
<br />
<label>
Message:
<textarea
name= "message"
value={formData.message}
onChange={handleChange}
className= "input-field"
/>
</label>
<br />
<button type= "submit"
className= "submit-button" >
Submit
</button>
</form>
);
}
export default App;
|
Javascript
import {
useState,
useEffect
} from 'react' ;
function useSyncExternalStore(key, initialValue) {
const [storedValue, setStoredValue] =
useState(
() => {
const item =
window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
}
);
useEffect(
() => {
window.localStorage
.setItem(key, JSON.stringify(storedValue));
}, [key, storedValue]);
return [storedValue, setStoredValue];
}
export default useSyncExternalStore;
|
Output:
Conclusion:
The useSyncExternalStore hook in React provides a simple yet powerful solution for synchronizing component state with an external data store. By persisting state across browser sessions and enabling cross-tab communication, this hook enhances user experiences and simplifies state management in React applications. Consider integrating useSyncExternalStore into your projects to unlock seamless state synchronization capabilities.
Share your thoughts in the comments
Please Login to comment...