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.