let action creators be passed via the provider
See original GitHub issueFirst off, thanks so much for Redux and the amazing tooling and introductory content around it. It’s been awesome to learn how all of the parts fit together.
I’ve been running into an issue while building out my first foray into a React/dux app dealing with action creators. I’m having to use mapDispatch
a ton for just passing the same action creators into the props
of each of my top-level components (without React Router I end up having around 5 top-level components so far, which I’ve called “containers” following the examples I’ve seen).
And the mapDispatch
that I’m writing is often just a super plain object like { loadUser, loadTeam, loadCollection }
that maps keys to keys. It’s getting really boilerplate-y to have to keep doing this all the time, when really I’d just like to have all my action creators already bound to my single store.
It would be amazing to be able to pass them into the <Provider>
:
<Provider store={store} actions={actions}>
<App />
</Provider>
And be able to use that inside components as:
componentWillMount() {
const { actions } = this.props
actions.loadUser(...)
actions.loadTeams(...)
...
}
From looking through the issues, I found that I’m not the first to suggest this, which means others are grappling with this problem too. Here are a few that mention discuss similar things:
- @mmerickel suggested it in https://github.com/rackt/react-redux/issues/1, except with the extra addition of using
mapDispatch
as well, which I think we can eliminate. - @maxguzenski suggested it in https://github.com/rackt/react-redux/issues/23.
- @gyzerok brought up the same pain point in https://github.com/rackt/redux/issues/231.
- And a few of the example snippets in the Readme actually mention a similar use case (of binding all action creators easily), but they do it at
connect
-time for each component, instead of at theProvider
level, which would mean not having to worry about it any more.
One time when it was brought up, it was discarded because of not wanting to pollute props
with all of the actions, since the “clobber likelihood” would be high. I totally get the concern about not wanting to pollute props
with tons of actions, but we can avoid that by nesting them in props.actions
instead.
Another time, @gaearon mentioned the (important) needs of code splitting. I think that’s definitely a use case to support, but surely we could have a load-later approach that works very similarly to the current mapDispatch
that would facilitate loading extra modules, while also making it easy for the main use case?
Curious to hear everyone’s thoughts.
From my initial use of both React and Redux, this would save me boilerplate code, and make it possible for people to write nicer boilerplate-reducing functionality on top of the base libraries.
Issue Analytics
- State:
- Created 8 years ago
- Comments:5 (2 by maintainers)
Top GitHub Comments
Absolutely! In my project so far, I have 5 container components, all of which need to “connected”. And I haven’t fleshed out the entire thing yet, so that number will grow for sure. For each one I have something along the lines of:
But just 3 actions for a container isn’t a lot; I expect some of them to need 10 or more. And each time I add or change an action, I have to make sure to update it in all of these places, or things break in ways that are sometimes hard to discern.
For example, I forgot to add
loadTeam
tomapDispatchToProps
since it was at the bottom of the file, and then proceeded to be pretty confused since the reference still existed, it just wasn’t to a “bound” action creator, so the error was non-obvious. Of course I could rewrite my import to make that not possible:If I actually gained from the configuration I might understand why it needed to be verbose, but for my own developer experience, the ideal for me would be to not have to worry about these kinds of things, and just have any function I exported from
* as actions
be bound to the store automatically. That way, even though I understand how it’s all wired up, I’d never have to think about the mappings again.Instead, I’d get a really simple workflow of: write an action creator function, and then go use it in my container components. Ideally as easily as just two things to think about:
If I was able to write this in myself from the top-level, I’d be more than glad. But it seems like the way the system is setup, there’s no way to pass other information into the
<Provider>
instance, so there’s no way I can do it without creating a singleton, which I want to avoid. (I may be missing a good trick here though—I guess I could attach bound actions to thestore.dispatch
function if I really wanted to, but that seems real hacky.) I’ve even looked into writing a different<Provider>
, but there’s so much logic in it that would need to be duplicated and kept up to date that it would be a huge pain to do.Let me know if that all makes sense, or if I’m doing something incorrectly. Happy to discuss more. Thanks!
Thanks for the response again. I actually did look at all of the examples before asking.
Both solutions solve the problem partially, but still require that the boilerplate in every file, even though I know I want every “connected” component to have access to all of the bound action creators, just like they have access to the store. Which means not only is it impossible for me remove the boilerplate completely (like with
store
passing), but it means that it’s impossible to pave overreact-redux
simply for this case from another library. It has to be done in the end files.I could create a separate
<Provider>
, which is pretty lightweight, but it seems like I’d also need implement a separateconnect()
as well, which has tons of extra logic that I’d need to carefully pass through, or reimplement, so maintaining it would be very non-trivial.It seems like adding all of the bound action creators onto
store.dispatch
as properties is the only way to do it from the top-level without having to repeat in each file, so I’ll go with that, even if it feels a bit hackish. Thanks