Underrated React Hook - useSyncExternalStore
Overview
Discover a hidden powerhouse in the React ecosystem: the “useSyncExternalStore” hook. This article delves into its transformative potential, challenging traditional state management paradigms. By seamlessly integrating external data sources and enhancing cross-component communication, this hook offers an unconventional yet powerful approach.
Journey with us as we demystify useSyncExternalStore. We’ll dissect its mechanics, unveil its benefits, and showcase practical applications through real-world examples. By the end, you’ll grasp how to wield this hook to streamline complexity, boost performance, and bring a new level of organization to your codebase.
Usage
According to React, useSyncExternalStore is a React Hook that lets you subscribe to an external store. But what is an “external store” exactly ? It literally takes 2 functions:
- The subscribe function should subscribe to the store and return a function that unsubscribes.
- The getSnapshot function should read a snapshot of the data from the store. Okay it’s might be hard to get at first. We can go into the example.
The Demo
For our demo today, I will go into a classic application: The “Todo List”.
The Store
First, we have to define the initial state:
export type Task = { id: string; content: string; isDone: boolean; }; export type InitialState = { todos: Task[]; }; export const initialState: InitialState = { todos: [] };
You can see that I defined the types and then created the state that has todos as an empty array
Now is the reducer:
export function reducer(state: InitialState, action: any) { switch (action.type) { case "ADD_TASK": const task = { content: action.payload, id: uid(), isDone: false, }; return { ...state, todos: [...state.todos, task], }; case "REMOVE_TASK": return { ...state, todos: state.todos.filter((task) => task.id !== action.payload), }; case "COMPLETE_TASK": const tasks = state.todos.map((task) => { if (task.id === action.payload) { task.isDone = !task.isDone; } return task; }); return { ...state, todos: tasks, }; default: return state; } }
Our reducer only has 3 actions: ADD_TASK, REMOVE_TASK and COMPLETE_TASK. This is the classic example of a to-do list logic.
Finally, what we are waiting for, the store:
let listeners: any[] = []; function createStore(reducer: any, initialState: InitialState) { let state = initialState; function getState() { return state; } function dispatch(action: any) { state = reducer(state, action); emitChange(); } function subscribe(listener: any) { listeners = [...listeners, listener]; return () => { listeners = listeners.filter((l) => l !== listener); }; } const store = { dispatch, getState, subscribe, }; return store; } function emitChange() { for (let listener of listeners) { listener(); } } export const store = createStore(reducer, initialState);
This code snippet illustrates the creation of a simple Redux-like state management system in TypeScript. Here’s a breakdown of how it works:
listeners Array: This array holds a list of listener functions that will be notified whenever the state changes.
createStore Function: This function is responsible for creating a Redux-style store. It takes two parameters:
- reducer: A reducer function responsible for calculating the next state based on the current state and dispatched action.
- initialState: The initial state of the application.
state: This variable holds the current state of the application.
getState Function: Returns the current state.
dispatch Function: Accepts an action object, passes it to the reducer along with the current state, updates the state with the result, and then calls the emitChange function to notify listeners about the state change.
subscribe Function: Accepts a listener function, adds it to the listeners array, and returns a cleanup function that can be called to remove the listener.
store Object: The created store object holds references to the dispatch, getState, and subscribe functions.
emitChange Function: Iterates through the listeners array and invokes each listener function, notifying them of a state change.
At the end of the code, a store is created using the createStore function, with a given reducer and initial state. This store can now be imported and used in other parts of the application to manage and control the state.
It’s important to note that this code provides a simplified implementation of a state management system and lacks some advanced features and optimizations found in libraries like Redux. However, it serves as a great starting point to understand the basic concepts of state management using listeners and a reducer function.
To use the useSyncExternalStore hook. We can get the state like this:
const { todos } = useSyncExternalStore(store.subscribe, store.getState);
With this hook call, we can access the store globally and dynamically, while maintain the readability and maintainability
Pros and Cons
The “useSyncExternalStore” hook presents both advantages and potential drawbacks in the context of state management within a React application:
Pros:
Seamless Integration with External Sources: The hook enables effortless integration with external data sources, promoting a unified approach to state management. This integration can simplify the handling of data from various origins, enhancing the application’s cohesion.
Cross-Component Communication: “useSyncExternalStore” facilitates efficient communication between components, streamlining the sharing of data and reducing the need for complex prop drilling or context management.
Performance Improvements: By centralizing state management and minimizing the propagation of state updates, this hook has the potential to optimize rendering performance, resulting in a more responsive and efficient application.
Simplicity and Clean Code: The hook’s abstracted API can lead to cleaner and more organized code, making it easier to understand and maintain, particularly in large-scale applications.
Reduced Boilerplate: “useSyncExternalStore” may reduce the need for writing redundant code for state management, providing a concise and consistent way to manage application-wide state.
Cons:
Learning Curve: Developers unfamiliar with this hook might experience a learning curve when transitioning from more established state management solutions. Adapting to a new approach could initially slow down development.
Customization Limitations: The hook’s predefined functionalities might not align perfectly with every application’s unique requirements. Customizing behavior beyond the hook’s capabilities might necessitate additional workarounds.
Potential Abstraction Overhead: Depending on its internal mechanics, the hook might introduce a slight overhead in performance or memory usage compared to more optimized solutions tailored specifically for the application’s needs.
Community and Ecosystem: As an underrated or lesser-known hook, “useSyncExternalStore” might lack a well-established community and comprehensive ecosystem, potentially resulting in fewer available resources or third-party libraries.
Compatibility and Future Updates: Compatibility with future versions of React and potential updates to the hook itself could be points of concern. Ensuring long-term support and seamless upgrades may require extra diligence.
Conclusion
In summary, useSyncExternalStore offers a unique approach to state management, emphasizing seamless integration and cross-component communication. While it provides several benefits, such as improved performance and simplified code, developers should carefully evaluate its compatibility with their project’s requirements and consider the potential learning curve and limitations.
The above is the detailed content of Underrated React Hook - useSyncExternalStore. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

JavaScript is the core language of modern web development and is widely used for its diversity and flexibility. 1) Front-end development: build dynamic web pages and single-page applications through DOM operations and modern frameworks (such as React, Vue.js, Angular). 2) Server-side development: Node.js uses a non-blocking I/O model to handle high concurrency and real-time applications. 3) Mobile and desktop application development: cross-platform development is realized through ReactNative and Electron to improve development efficiency.

This article demonstrates frontend integration with a backend secured by Permit, building a functional EdTech SaaS application using Next.js. The frontend fetches user permissions to control UI visibility and ensures API requests adhere to role-base

I built a functional multi-tenant SaaS application (an EdTech app) with your everyday tech tool and you can do the same. First, what’s a multi-tenant SaaS application? Multi-tenant SaaS applications let you serve multiple customers from a sing

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.
