Skip to content

[Performance] Slice contexts (createSliceWithContext) #2202

Closed as not planned

Description

What is the new or updated feature that you are suggesting?

Problem:

One of the slowest parts of redux is that there can be a lot of subscribers to the store with their custom state comparers. If we have 1000 subscribers and 100 actions are triggered per second (like on startup of the chatting app), 100 000 comparisons are made per second.

One possible solution is to use multiple stores, but this can lead to various issues.

Suggestion:

The same performance of having multiple stores can be achieved with single store. There is already an ability to make custom contexts and hooks, but currently it makes sense only for multiple stores.

UPDATED: Ability to provide the same store but with slice's context and hooks should be added with the new createSliceWithContext function:

export const {
  // new prop for slice selectors - ones that select from slice state, not the root
  // basically the same provided while creating the slice, nothing new here - just pass them here
  sliceSelectors: { 
    ...
  },
  // usual selectors can be kept as well
  selectors: { ... }
  // new props for context and provider
  context: AccountSliceContext,
  provider: AccountSliceProvider,
  hooks: {
    // new hook that connects to the new context with the slice state
    useSelector: useAccountSelector,
  },
  // other returned values are the same
  ...
} = createSliceWithContext({
  // everything is the same as in usual createSlice 
  name: 'account',
  selectors: {
    ... 
  },
  ...
})

const App = () => {
  return (
    <Provider store={store} />
      <AccountSliceProvider store={store}>
        <RootModule />
      </AccountSliceProvider>
    </Provider>
  );
}

const RootModule = () => {
  // here we got the state of the account state, not the whole redux state
  // this selector should not be executed and compared on redux state updates when account state does not change
  const accountState = useAccountSelector(accountState => accountState, customEqualityFn) 

  return null
}

Please also check the initial suggestion as it provides more generic solution, and can be implemented as well / instead:

OLD Ability to provide the same store but with domain selector should be added:
const store = createStore(reducer);

const SomeDomainContext = React.createContext(null);
const someDomiainSelector = (state) => state.someDomain

// custom hook for a specific domain
export const useSomeDomainSelector = createSelectorHook(MyContext, someDomainSelector)

const App = () => {
  return (
    <Provider store={store} />
      <Provider store={store} selector={someDomainSelector} context={SomeDomainContext}>
        <RootModule />
      </Provider>
    </Provider>
  );
}

const RootModule = () => {
  // here we got the state of the selected domain, not the whole redux state
  // this selector should not be executed and compared on redux state updates when domain does not change
  const someDomainState = useSomeDomainSelector(domainState => domainState, customEqualityFn) 

return null
}

Why should this feature be included?

This will make using multiple stores totally obsolete, but will fix performance issues caused by single store.

What docs changes are needed to explain this?

https://react-redux.js.org/using-react-redux/accessing-store

Add recommended practise here:
https://redux.js.org/style-guide/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions