-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
let action creators be passed via the provider #249
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I don't understand what is boilerplatey about specifying a single-line function several times. Can you give specific examples? |
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: import { loadCollection, loadItem, loadTeam } from '../../actions'
// ...
function loadData(props) {
const { loadCollection, loadItem, loadTeam } = props
}
// ...
const mapDispatchToProps = {
loadCollection,
loadItem,
loadTeam
}
// ...
const Connected = connect(mapStateToProps, mapDispatchToProps)(Component) 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 import * from '../../actions'
// ... but then I have to make my dispatch mapping more verbose ...
const mapDispatchToProps = {
loadCollection: actions.loadCollection,
loadItem: actions.loadItem,
loadTeam: actions.loadTeam
} 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 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: export function loadCollection(id) {}
// ...
const { actions } = this.props
actions.loadCollection(id) 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 Let me know if that all makes sense, or if I'm doing something incorrectly. Happy to discuss more. Thanks! |
You can provide you own connect, and use reselect to memoize it. import { createSelector } from 'reselect'
import { bindActionCreators } from 'redux'
import { connect as reduxConnect } from 'react-redux'
import { * as myActions } from './actions'
// bindActionCreators will be execute ONLY on first time
// or when dispatch instance changes
const mapDispatchToProps = createSelector(
dispatch => dispatch,
dispatch => ({actions: bindActionCreators(myActions, dispatch)})
)
const connect = (mapStateToProps, mergeProps) => {
return reduxConnect(mapStateToProps, mapDispatchToProps, mergeProps)
}
// use this connect on yours Components
export default connect With this you can provide many personalized connects as you want:
|
Please take a close look at all examples in the docs. What you want is either import * as actions from '../actions';
export default connect(
mapStateToProps,
actions
)(MyComponent);
// this.props.loadData() or import * as actions from '../actions';
import { bindActionCreators } from 'redux';
const mapDispatchToProps = (dispatch) => {
return {
actions: bindActionCreators(actions, dispatch)
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(MyComponent);
// this.props.actions.loadData() There's no need to explicitly enumerate them. By the way you can totally write your own Provider. Not sure what logic duplicate you are concerned about because there is almost no logic there—it just puts store in context and that's it. |
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 I could create a separate It seems like adding all of the bound action creators onto |
Remove React-specific code in favor of gaearon/redux-react
First 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 theprops
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>
:And be able to use that inside components as:
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:
mapDispatch
as well, which I think we can eliminate.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 polluteprops
with tons of actions, but we can avoid that by nesting them inprops.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.
The text was updated successfully, but these errors were encountered: