How to access redux store from action creator?
You'll need thunk in order to enhance your action creators. the reason why you're getting the "must be plain objects" error is because your action creator is returning a function(), not an object. Thunk allows you to return functions in your action creators and with it, the code you wrote should work.
import { createStore, combineReducers, applyMiddleware } from "redux"
import thunk from "redux-thunk"
const store = createStore(combineReducers({
data1: reducer1,
data2: reducer2
}), {}, applyMiddleware(thunk))
Hope that works.
Accessing state in a Redux action
You can get the state in your actions too.
For example in this action you can do this:
export function isAuthz(allowed, except) {
return (dispatch, getState) => {
const state = getState()
// do stuff
}
}
Redux accessing state from action
Your action creators should generally be pure functions that don't result in side effects. The reason you don't want to access state in your action creator is because that means the result of setCategory()
cannot be predicted based on its arguments. The whole point of Redux is to be able to reason about the state of your application in a straightforward way. If you can't easily follow the change in state that resulted from a given action being dispatched, that becomes much harder.
When you need to conditionally dispatch an action based on whether some part of state exists or not, then it's clearer to do that in "client" code (i.e. the client from Redux's perspective), which in this case would probably be a component. You can do the check and then dispatch some kind of LOAD_DATA
action if the data is missing.
However, if you need to do something asynchronous, then you should investigate common patterns for async operations in Redux, or use an existing library, like Redux Thunk or redux-saga
.
Best Way to Get State from Redux Store in Action Creator
I recommend that you take a look at reduce-reducers
.
The well-known combineReducers()
that Redux provides runs reducers in parallel, if you will, with each reducer only being aware of the piece of state within its own scope. Other configurations of reducers are possible. For example, you could reduce an array of reducers, running each in series, meaning that each will get a freshly computed state object from its precursors to use to compute the new state that it will pass on.
In your case, this would allow your reducer to know about selectedNode
while reducing your ADD_CHILD
action. If the parentId
is not set in the action, the reducer can default to selectedNode
. You just have to make sure that the reducer that changes selectedNode
runs upstream of the one handling ADD_CHILD
.
This covered in a nice way (with examples) in the Redux docs Redux docs: sharing-data-between-slice-reducers.
Using this pattern will allow you to avoid thunks, maintain simple action creators, still have simple component selectors, keep your state logic in the reducers where it belongs, and still keep your reducers pure. Having tried most of those other patterns you mentioned myself, I recommend this approach.
Good luck!
Redux pattern for getting state in action creator
I always follow the latter example, meaning that my action creators are not dependent on a store
. However, there was a case when I had to pass user token to almost every action that required interaction with server API. Instead of repeatedly pass it to every action creator or accessing it within with getState()
I wrote a custom middleware (not that difficult) that would recognize these actions and enrich them with another prop called userToken
.
Back to the Dan Abramov answer. He says in a comment:
It’s fine to read from the store in the action creator.
which is confusing to me, but I think what he meant is that is fine to do it for certain reasons:
I think it’s acceptable is for checking cached data before you make a
request, or for checking whether you are authenticated (in other
words, doing a conditional dispatch)
... and that using getState
may result in a situation where:
... it is hard to trace where those incorrect values come from
because they are already part of the action, rather than directly
computed by a reducer in response to an action.
What I think he means is that action creators should not pass updated parts of the store that get replaced by the reducer, but action should describe what is happening and the reducers should handle the update:
Not:
here is the new
item
list - replace it in the store
But:
we need to remove the
item
with id:5
- handle it
...which is a bit different scenario than accessing a value from store to use it in a request. I advice you to read the linked blog. It answers in deep your question and there are some arguments with examples about whats best. TL;DR - it's a debate which approach is better.
Related Topics
Difference Between Textcontent VS Innertext
How to Change Href of <A> Tag on Button Click Through JavaScript
What Does Curly Brackets in the 'Var { ... } = ...' Statements Do
Why Is Value Undefined at .Then() Chained to Promise
How to Open a New Window and Insert HTML into It Using Jquery
Refresh a Div That Has a Google Ad Inside It
How to Use JavaScript to Change the Form Action
Populate One Dropdown List Based on the Selection of Other Dropdown List
How to Determine Which HTML Page Element Has Focus
How to Check If a JavaScript Object Is a Dom Object
How to Get Current Value of Rxjs Subject or Observable
React-Router - Pass Props to Handler Component
JavaScript Require() Function Giving Referenceerror: Require Is Not Defined
How to Get the Mouse Position Without Events (Without Moving the Mouse)
Making a JavaScript String SQL Friendly
Change Color of Specific Words in Textarea
Error: Failed to Execute 'Appendchild' on 'Node': Parameter 1 Is Not of Type 'Node'