Sync React Component State Without Heavy Libraries: Custom Hook & Pub‑Sub

This article explains how to synchronize state across distant React components without relying on heavy libraries, using a custom hook and a publish‑subscribe model, and discusses optimizations such as avoiding redundant updates and incorporating a simple reducer for efficient change detection.

Huolala Tech
Huolala Tech
Huolala Tech
Sync React Component State Without Heavy Libraries: Custom Hook & Pub‑Sub

Background

When developing frontend features, we often need to synchronize internal state across distant components. For example, a ThemeSwitch component changes its color state and wants to update other components for a live theme preview.

Typically Redux is used, but two questions arise: 1) Can we sync state simply without third‑party libraries? 2) How do state‑management libraries work internally?

Just want to sync a state—can it be done without adding a library?

What is the internal implementation principle of state‑management libraries?

Problem Analysis

Two analysis approaches exist: 0‑1 (run code step by step) and 1‑0 (start from the desired result). We adopt the 1‑0 method.

1. Notification Sync

When ThemeSwitch changes the theme via setColor(newColor), we simply need to notify other components to execute the same setColor(newColor) to update their state.

2. How to Notify?

Collect the setColor calls and invoke them—a classic publish‑subscribe model. Define a custom hook useColorState as a controller to maintain subscription‑publish functionality.

Solution

Implement a custom hook that intercepts component state definitions to bind subscription relationships and provide publish‑subscribe capability.

1. Custom Hook

export default function useColorState() {
  const [color, setColor] = useState();
  return [color, setColor];
}

2. Publish‑Subscribe Model

class ColorChanger {
  constructor() {
    this.color = 'orange';
    this.callBacks = [];
  }
  subscribe(cb) {
    this.callBacks.push(cb);
  }
  publish() {
    this.callBacks.forEach(cb => cb(this.color));
  }
}

3. Subscription

Initialize subscription and internal state.

let colorChanger;
function useColorState() {
  // ...
  useEffect(() => {
    colorChanger = colorChanger || new ColorChanger();
    colorChanger.subscribe(setColor);
    setColor(colorChanger.color);
  }, []);
  // ...
}

4. Publish

The hook returns a changeColor function that updates the ColorChanger and triggers publish.

function useColorState() {
  // ...
  const changeColor = (val) => {
    colorChanger.setColor(val);
  };
  return [color, changeColor];
}
class ColorChanger {
  // ...
  setColor(color) {
    this.color = color;
    this.publish();
  }
}

5. Unsubscribe

When a component unmounts, remove its setColor from the callbacks.

class ColorChanger {
  // ...
  unsubscribe(cb) {
    this.callBacks.splice(this.callBacks.indexOf(cb), 1);
  }
}
function useColorState() {
  useEffect(() => {
    // ...
    return () => {
      colorChanger.unsubscribe(setColor);
    };
  }, []);
}

Optimization

Small optimization: avoid publishing when setColor receives the same color, as publishing is costly.

setColor(color) {
  if (this.color === color) return;
  // ...
}

2. Reducer

Redux uses reducers to efficiently compare old and new state. For a simple string color we can implement a reducer.

Define a reducer and integrate it into useColorState.

const newState = reducer(oldState, action);
function colorReducer(state = { color: 'orange' }, action) {
  return action.color === state.color ? state : { color: action.color };
}
function useColorState(colorReducer) {
  colorChanger = colorChanger || new ColorChanger(colorReducer);
  // ...
}
class ColorChanger {
  setColor(action) {
    const newState = this.colorReducer(this.state, action);
    // ...
  }
}

Further optimizations include wrapping changeColor with useCallback, queuing publishes, etc.

Conclusion

The article discusses common component state synchronization in web development and presents a simple solution using a custom hook and publish‑subscribe pattern, with notes on optimization and reducer usage for efficient change detection.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ReduxReactstate synchronizationCustom Hook
Huolala Tech
Written by

Huolala Tech

Technology reshapes logistics

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.