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
Pass props into state selector #36
Conversation
Please see this discussion: #41. |
Sorry, I might be missing something but #41 seems to be a bug about props being stale rather than making them accessible to
Do you mean Say I've got a users store and I want to render a single user from that store but I don't want to pass in any action creators. Based on your example I would have to do this: @connect(
state => { users: state.users },
null,
(stateProps, dispatchProps, defaultProps) => { user: stateProps[defaultProps.userId] }
)
class User extends React.Component {
render () {
const {user} = this.props
return <div className='User'>{user.name}</div>
}
}
React.render(<User userId={123} />) With my proposed change all you'd need to do is @connect((state, props) => { user: state.users[props.userId] })
class User extends React.Component {
render () {
const {user} = this.props
return <div className='User'>{user.name}</div>
}
}
React.render(<User userId={123} />) Maybe you're usage is different but selecting something from state based on the parent props is something I do in nearly every 'smart' component. This proposed change makes this use case significantly simpler. Do you have any specific motivations for keeping the current API? |
+1 I found the new API quite verbose for this (seemingly common) use-case. But I'm not if there's a specific reason that I'm missing for why props aren't provided to |
So you need to select state by ID but not action creators? Why? Wouldn't you need that in real apps, as opposed to simple examples? My only concern with adding props to first parameter is because people will expect it to be available to |
Ah, makes sense to me. On Sun, 9 Aug 2015 13:31 Dan Abramov notifications@github.com wrote:
|
About 50% of our components don't need action creators at all, they just render data. For those that we just pass the prop value from within the component @connect((state, props) => { user: state.users[props.userId] }, { updateUser })
class User extends React.Component {
render () {
const {user} = this.props
return (
<input
type='text'
ref='name'
value={user.name}
onChange={::this.updateUser} />
)
}
updateUser (e) {
const {userId} = this.props
this.props.updateUser(userId, {
name: e.target.value
})
}
} To me this is much more understandable since its clear where an action creators arguments are coming from. |
Why not leave that as a note in the documentation for |
But it's asymmetric. You pass just one |
I still personally prefer to know precisely where all arguments to a function come from rather than having to trace through multiple function calls but I completely see where you're coming from. What about when your component doesn't need action creators? A common use case in my code base but maybe I'm in a minority. Unless I'm missing something you still have to do this
|
We can reorder parameters in @connect(
state => ({
users: state.users
}),
null,
(ownProps, stateProps) => ({
user: stateProps.users[ownProps.userId]
})
) Is it really that bad? We get both symmetry and better performance because we don't have to recompute |
With destructuring: @connect(
({ users }) => ({ users }),
null,
({ userId }, { users }) => ({ user: users[userId] })
) |
Personally that doesn't exactly feel intuitive to me What about if you could pass in an object literal to @connect({
bind: { updateUser }, // default null
select: state => { users: state.users }, // default state => state
merge (props, state, actionCreators) {
return {
user: state.users[props.userId],
updateUser: (text) => actionCreators.updateUser(userId, { text })
}
}
}) With those defaults and your suggestion of moving props to being the first argument we can reduce it down to @connect({
merge (props, state) {
return {
user: state.users[props.userId]
}
}
}) |
also, sorry, don't want to be annoying. I'd just like to find a nice API :) |
Performance is more important to this library than succinctness. We can sacrifice some convenience if that means people will get more performant apps by default. We will also never suggest "bad perf" patterns as defaults. |
Fair enough, will close this then |
Dont want tot reopen this request on purpose; but this use-case is very much like mine. Looking ahead I was wondering whether Reselects (memoized) selectors can then be applied tot the filter in the mergeProps? Thanks in advance |
Can you ask this in Reselect repo? I'm not sure how to do that, but I'd sure like to know :-) |
I am finding this to be a really frustrating use case for me. I almost always want Another option, we could check |
But we would still have to rebind on every prop change when they aren't equal, but we don't really know if user even used props.
Yes, I guess we'll have to resort to this to satisfy everybody. :-) Normally I hate to do this, but this seems like a valid use case. Want to make a PR? |
I created #52, let's discuss there. |
Released as 0.9.0, please verify. |
It would be really handy if you could have access to the props when selecting state. This PR passes them in as a second argument to
mapStateToProps