Skip to Content
Multi-Platform Content Distribution 🚀 Read more → 
DocumentationQuickstart: Redux

Quickstart with Redux

Easily integrate Redux to provide a simple way to manage state across your browser extension.

We forked redux-persist  which you can utilize along with redux-persist-webextension-storage  to persist your Redux state using chrome.storage.

⚠️

Support for Redux is provided by the open-source community at large. If it does not work, we welcome your contribution! For custom integration, we offer a consultation service. Please email support@plasmo.com for more detail.

Increment Example

Let’s make a basic extension that increments and decrements a counter.

Create Your Slice

counter-slice.ts
import { createSlice } from "@reduxjs/toolkit" export interface CounterState { count: number } const counterSlice = createSlice({ name: "counter", initialState: { count: 0 }, reducers: { increment: (state) => { state.count += 1 }, decrement: (state) => { state.count -= 1 } } }) export const { increment, decrement } = counterSlice.actions export default counterSlice.reducer

Create Your Store

store.ts
import { configureStore } from "@reduxjs/toolkit" import { localStorage } from "redux-persist-webextension-storage" import { FLUSH, PAUSE, PERSIST, PURGE, REGISTER, REHYDRATE, RESYNC, persistReducer, persistStore } from "@plasmohq/redux-persist" import { Storage } from "@plasmohq/storage" import counterSlice from "~counter-slice" const rootReducer = counterSlice const persistConfig = { key: "root", version: 1, storage: localStorage } const persistedReducer = persistReducer(persistConfig, rootReducer) export const store = configureStore({ reducer: persistedReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: { ignoredActions: [ FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER, RESYNC ] } }) }) export const persistor = persistStore(store) // This is what makes Redux sync properly with multiple pages // Open your extension's options page and popup to see it in action new Storage().watch({ [`persist:${persistConfig.key}`]: () => { persistor.resync() } })

The thing to note is the new Storage().watch() call. This will automatically resync the store whenever the Redux store changes in chrome.storage.

Using in React

options.tsx
import { Provider } from "react-redux" import { PersistGate } from "@plasmohq/redux-persist/integration/react" import { CounterView } from "~counter" import { persistor, store } from "~store" function Options() { return ( <Provider store={store}> <PersistGate loading={null} persistor={persistor}> <CounterView /> </PersistGate> </Provider> ) } export default Options

Using the PersistGate will ensure the child components don’t render until the store is ready.

Using in a Background Service Worker

background.ts
import { persistor, store } from "~store" persistor.subscribe(() => { console.log("State changed with: ", store?.getState()) })

Full Example

See with-redux  for a complete example.

Last updated on