Is there any way I can access getState() from a non-React Component nor an Action file?
I have a Util file that needs to be able to call getState() (or just any way to get the most updated state). Usually I just pass in part of the state that I need for the function, but I have one particular function that loops and needs to get the latest function every time it does loop.
I was reading more into connect() but it seems like it only works for Components. I was looking into Middleware, but it seems like that only interacts with executing Actions and I'm just at a road block where I don't know how to move forward.
Thank you
You might consider leveraging the subscribe(listener) method in the Redux Store.
The subscribe method allows you to attach a callback that is called every time the state tree may have potentially changed. This would let you call getState() inside the listener to get the current state tree.
The subscribe method is a low level API and is a bit clunky. The documentation for Redux also provides some linking to examples leveraging the Observable property of the Redux store so you can do something a bit more abstracted.
Related
I have a react project configured with redux for state management.
For api calls I use a file called axiosInstance. In this file I need to have access to redux store (and I have access importing store and using getState - store.getState()). Now the problem is that I want also to update the redux state from this file (axiosInstance).
How I can update redux store from this file (which is not a react component) in a efficient method?
Okay, I assume that you are using Axios for the network calls.
tl;dr
Use store.dispatch(action) and action to make changes to store state
Yes, the store can be accessed with store.getState(), you can also change state with store.dispatch(action). as per the docs
Dispatches an action. This is the only way to trigger a state change.
The store's reducing function will be called with the current getState() result and the given action synchronously. Its return value will be considered the next state. It will be returned from getState() from now on, and the change listeners will immediately be notified.
This happens because of the functional paradigm that redux follows (google for more).
Now, the action has to be defined with an actionCreator, or simply you could call .dispatch() with an inline object with one string property as {type: 'name-of-action'}. This prompts the store to change the state.
You may require redux-thunk for async actions.
Conclusion:
Let's save some trouble here as you may have many calls to the store, you can create a context that handles the AxiosInstance (as there is already a different file for that).
Make a context in the AxiosInstance file and then you can start dispatching actions as per the network responses. this will save you a lot of trouble as the state is updated by redux without actually looking at it much.
Explain briefly about... Why should you dispatch an action to update the state and not update the store directly in react/redux?
Redux is a dataflow pattern that is event (=action)-based. Only actions lead to store changes. Also, those have to happen without changing the old state, but by creating a new one.
This is a base assumption and un-bendable rule, because that is the purpose of Redux - moving applciation logic out of your UI layer.
All tooling depends on that assumption - e.g. react-redux will only check for new state after a dispatch and it will do so by comparing current and last state value.
If you want to directly modify it, you simply have gone for the wrong library.
There are libraries that allow for such things, like mobx or valtio, but it will not work with Redux.
Let's say i have a property in the store called state.items.byId each time this is updated (various parts of the application) i want to intercept the value before i'ts updated and run a function to update some properties on it before it's updated.
I don't know the terminology and i'm quite new to redux, but if someone could point me in the right direction that would be great!
I have searched and found redux-watch but i'm not 100% sure if this is the right approach
below shows the data flow in a redux application. View dispatches an action, the action
object is a blue-print telling the reducer what changes it needs to make to the store state. Any
change in the redux store state needs to pass through this cycle.
redux-watch provides you a subscription based mechanism notifying you after a property is
changed. If you want to intercept a property before its changed you can write a custom
middleware and handle any side-effects inside it.
So in plain react, setState triggers the render method. Now, about Redux, let's say I fire an action, the state returned from the reducer(s) is totally new, so it sounds like every component should get updated, though I know it's not true because when I debug my app I can see it, plus it sounds like awful performance. So my question is, does redux look in each component what state slice it needs? in mapStateToProps? and generally how does Redux decide when to call the render method?
I know Redux has optimizations in it... thanks...
A Redux store offers a subscribe() method. When you use connect(), it generates wrapper components that automatically subscribe to the store when they are created. Each individual connected component is a separate subscriber.
When an action is dispatched, the store runs all the subscription callbacks. The wrapper components then call store.getState(). As a first check, if the root state object is === identical to the previous one, the component will stop there. (This is one reason why direct mutation of state in a reducer is bad.)
The next step is to call the provided mapState function and pass in the current state object. The wrapper component then compares the contents of the object returned from mapState against the contents of the object returned last time, using a shallow equality comparison check. If any of the contents have changed based on that shallow check, then the component knows it needs to re-render the "real" component with the new data. (Again, the "shallow" check is another reason why mutation is bad.)
I'm in trouble with React and Flux... We have an application that is pretty similar to the new Flux chat example. We have the famous error "cannot dispatch in the middle of dispatch". But, it's hard to us to think in a good way to resolve this problem in some cases.
Our doubt is identical to this: https://groups.google.com/forum/#!topic/reactjs/mVbO3H1rICw, but I can't understand very well the solution adopted. As far as I understand, is not a very elegant solution.
Here is the sequence of events:
Action A is dispatched;
The Store updates it's internal state and emits the change message;
A react component X receives the change message (by the callback of the listener) and updates it's state (setState);
The component X renders and as part of that a new component Y is mounted too. We choose the component (Y, Z, etc...) to be rendered using the information of the state;
The new component Y needs data to display that isn't initially loaded. So we call a API in the componentDidMount() of the component Y, that calls an action B.
Then, with the new dispatcher in the Action B, we have this dispatch error.
If you consider that our application logic have some issue, I can bring some practicals examples to show why this scenario is common for us. Any idea of how refactor this "flux" is very welcome.
Thanks for any help!
i think you need to use the waitFor token from the dispatcher before launching action b (youre using the dispatcher from the flux npm module right?). additionally, what can you do is make the ajax call from your store during action A if youre always going to need that data from action b.
solution b would look like this in /* store.js */
Dispatcher.register(function(payload){
switch payload.type {
case ACTION_A:
/* do your state logic */
StoreDataAccessLayer.apiCall()
}
}
where you have a Data Access Layer class / object that wraps your ajax call to the api. using the state from your store as inputs, and calling trigger change from the success function. this is the primitive solution i've seen when using the flux npm module if youre not going with waitFor