atlassian / react-sweet-state

Shared state management solution for React

Home Page:https://atlassian.github.io/react-sweet-state/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Q: How to trigger store action from outside component?

kwiniarski97 opened this issue · comments

I have some axios interceptor written that in some circumstances should dispatch an action from core store.
I tried exporting a store object and importing it into the file, but that does not call the inner function.
How can you achieve this behaviour?

I've made a simple reproduction, what is not working. https://codesandbox.io/s/cool-pine-pwepc?file=/src/App.js
When clicking on the "normal on click" the counter is incremented. I don't know however how can I make it work the same way for "outside fn click"

For each of my stores I like to export a StoreInstance using defaultRegistry like so:

// store.ts
import { defaultRegistry, createStore } from 'react-sweet-state'

const Store = createStore({
  name: 'defaultStore',
  initialState,
  actions,
})

export default defaultRegistry.getStore(Store)

Now I can just import this file and have reference directly to the StoreInstance which allows me to perform and actions and access its state outside of a component.

import Store from './store'

// Perform action
Store.actions.doThis()

// Retrieve state
Store.storeState.getState().someState

I tried it and it works :) Thank you, @ninjz.

Is this part of the documentation?

Doesn't look like it. Seems like it would be a great addition to it though.

I only found out about defaultRegistry through digging into the code a while back. I've always felt the need to have access to the stores outside the component so it really felt limiting when this wasn't presented as a feature.

cc: @albertogasparin

The reason why that is not documented (or typed) and is still a private API is because works only for global stores and does not handle Container props. As soon as you add a Container those expectations break and we either get a different instance or the actions might not receive the expected arguments.
So I would suggest grabbing the value from the render tree as a more solid way (even if a bit more verbose) to ensure the store you retrieve is actually the one gives data to your components.
It can be done by adding a hook that exposes state/actions to a module level variable:

// store.ts
import { createStore, createHook } from 'react-sweet-state'

const Store = createStore({
  name: 'defaultStore',
  initialState,
  actions,
});

const instance = { state: null, actions: null };

const useStore = createHook(Store);

const useStoreReference = () => {
  const [state, actions] = useStore();
  instance.state = state;
  instance.actions = actions;
  return null;
}

export default instance;

Now rendering useStoreReference will provide the accurate instance.