Build a Simple Redux from Scratch and Integrate It with React

This article explains Redux’s core concepts, demonstrates how to implement a basic createStore function in JavaScript, and shows how to integrate it with React using a custom Provider and connect higher‑order component for state sharing across components.

KooFE Frontend Team
KooFE Frontend Team
KooFE Frontend Team
Build a Simple Redux from Scratch and Integrate It with React

Redux is a popular state management tool that stores the entire application state in a single place for centralized management. This article implements a simple Redux from scratch.

Core concepts of Redux

The entire application state is stored in a single store.

The only way to change state is by dispatching actions.

Reducers describe how actions transform the state.

Store API

getState() – retrieve the current state.

dispatch(action) – update the state.

subscribe(listener) – register a listener.

The function returned by subscribe can unsubscribe the listener.

Implementing createStore

const createStore = (reducer, preloadedState) => {
  let state = preloadedState;
  const listeners = new Set();
  // dispatch(action) updates state
  const dispatch = (action) => {
    state = reducer(state, action);
    listeners.forEach(listener => listener());
  };
  // getState() returns state
  const getState = () => state;
  // subscribe registers a listener
  const subscribe = (listener) => {
    listeners.add(listener);
    return unsubscribe(listener);
  };
  // unsubscribe removes a listener
  const unsubscribe = (listener) => () => {
    listeners.delete(listener);
  };
  return { dispatch, subscribe, getState };
};

Using the store

const reducer = (state = { count: 0 }, action) => {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
};
const store = createStore(reducer);
const unsubscribe = store.subscribe(() => {
  const state = store.getState();
  console.log(state.count);
});
store.dispatch({ type: "increment" });
unsubscribe();

Integrating with React

The store can be used in React components; when the store changes, components are forced to re‑render.

const Counter = () => {
  const [, forceUpdate] = React.useState();
  useEffect(() => {
    const unsubscribe = store.subscribe(() => {
      forceUpdate({});
    });
    return () => {
      unsubscribe();
    };
  }, []);
  return (
    <div onClick={() => store.dispatch({ type: "increment" })}>
      {store.getState()?.count || 0}
    </div>
  );
};

Simple React‑Redux implementation

First, define a Provider component using React Context to share the store.

const ReduxContext = React.createContext();
const Provider = ({ store, children }) => {
  const contextValue = useMemo(() => ({ store }), [store]);
  return (
    <ReduxContext.Provider value={contextValue}>
      {children}
    </ReduxContext.Provider>
  );
};

Then, create a connect higher‑order component that maps store state and dispatch to component props and forces a re‑render when the store updates.

const connect = (mapStateToProps, mapDispatchToProps) => {
  return (Component) => {
    return (props) => {
      const [, forceUpdate] = useState({});
      const { store } = useContext(ReduxContext);
      const stateToProps = mapStateToProps(store.getState());
      const dispatchToProps = mapDispatchToProps(store.dispatch, props);
      useEffect(() => {
        const unsubscribe = store.subscribe(() => {
          forceUpdate({});
        });
        return () => {
          unsubscribe();
        };
      }, [store]);
      return <Component {...props} {...stateToProps} {...dispatchToProps} />;
    };
  };
};

Usage example:

const Counter = (props) => (
  <div onClick={props.onClick}>{props.count}</div>
);
const CounterWrap = connect(
  state => ({ count: state.count }),
  dispatch => ({
    onClick: () => {
      dispatch({ type: "increment" });
    }
  })
)(Counter);
const App = () => (
  <Provider store={store}>
    <CounterWrap />
  </Provider>
);
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.

FrontendJavaScriptReduxstate-managementReActTutorial
KooFE Frontend Team
Written by

KooFE Frontend Team

Follow the latest frontend updates

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.