-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
connect assumes store prop is a redux store #1393
Comments
This behavior has existed in every version of React-Redux except v6. The only reason it didn't exist in v6 was because connected components didn't subscribe to the store directly in that version. All other versions have accepted a prop named I'm curious how you didn't run into this previously. Has your codebase only used React-Redux v6 so far, and you just now upgraded to v7? I agree it should probably be a bit better documented, but this is well known behavior, and not something we're planning to change at this time. I also don't see a need to specifically re-enable the "override key" behavior either. I'm going to close this for now. If you have very strong reasons why this should be reconsidered, though, please feel free to keep discussing this further, and we can talk through the issue. |
Hi @markerikson thanks for getting back to me so quickly. The codebase is one we are migrating to Redux from an alternate flux implementation, so v7 is the first version it has used. It has dozens (maybe 100?) connected components that take a store prop (which means a physical store, not a redux store). I've started to rename that prop to I've considered writing a wrapping HoC to do the prop renaming, but in order to support the full interface of Restoring this behavior in redux seemed to be the path of least resistance. I totally understand why it exists, and it's a convenient thing for testing and other reasons I'm sure, but coopting the For posterity, it appears |
Yeah, to clarify: the notion of Interestingly, I think the original intent of Digging through the issues, the most relevant historical discussions are: I understand the situation you're in, and I sympathize. Migrations are always tough, and more so when you're having to fight the tools you're dealing with. At the same time, I'm very hesitant to (re-)add something to our public API that is only for a very niche use case, and that no one else has expressed an interest in so far. As an alternate idea: we could potentially tweak the logic in // The store _must_ exist as either a prop or in context
- const didStoreComeFromProps = Boolean(props.store)
+ const didStoreComeFromProps = Boolean(props.store) && props.store.getState && props.store.dispatch
const didStoreComeFromContext =
Boolean(contextValue) && Boolean(contextValue.store)
invariant(
didStoreComeFromProps || didStoreComeFromContext,
`Could not find "store" in the context of ` +
`"${displayName}". Either wrap the root component in a <Provider>, ` +
`or pass a custom React context provider to <Provider> and the corresponding ` +
`React context consumer to ${displayName} in connect options.`
)
- const store = props.store || contextValue.store
+ const store = didStoreComeFromProps ? props.store : contextValue.store
@timdorr , thoughts? |
I totally understand not wanting to add to the public API for just us. Your proposed solution sounds great to me—I think it's a good idea. |
I think I've worked around it successfully. Can you see any problems with this approach, @markerikson, or is there a better way to accomplish it? It'd still be great if your suggestion was implemented so I could remove this wrapper. const fixProps = ({ __store, ...props }) => ({ ...props, store: __store })
export const connect = (
mapStateToProps,
mapDispatchToProps,
mergeProps,
options
) => WrappedComponent => {
const ConnectComponent = reduxConnect(
mapStateToProps && mapStateToProps.length > 1
? (state, ownProps) =>
mapStateToProps(state, fixProps(ownProps))
: mapStateToProps,
mapDispatchToProps && mapDispatchToProps.length > 1
? (dispatch, ownProps) =>
mapDispatchToProps(dispatch, fixProps(ownProps))
: mapDispatchToProps,
(stateProps, dispatchProps, ownProps) => {
const fixedOwnProps = fixProps(ownProps)
return mergeProps
? mergeProps(stateProps, dispatchProps, fixedOwnProps)
: { ...fixedOwnProps, ...stateProps, ...dispatchProps }
},
options
)(WrappedComponent)
const ProtectedComponent = ({ store, ...props }) => {
return React.createElement(ConnectComponent, { ...props, __store: store })
}
ProtectedComponent.WrappedComponent = WrappedComponent
return hoistStatics(ProtectedComponent, ConnectComponent)
} |
Mmm... you could probably try customizing the https://react-redux.js.org/api/connect#mergeprops-stateprops-dispatchprops-ownprops-object |
That only handles the final props, I want it to be transparent in any usage of |
Belatedly fixed in https://github.com/reduxjs/react-redux/releases/tag/v7.1.2 . Hope this helps! |
It helps greatly, thank you! We just completed our redux migration, so now I can remove my workaround. |
Great! Next suggestion: go try out https://redux-starter-kit.js.org :) (maybe I shoulda said that before you got involved in the migration...) |
Ah, yeah that may have helped. Looks great. I might suggest a docs page about typescript, looks like you have decent support for it, but I had to dig into the code to find it. Also, not sure why this is tested for: https://github.com/reduxjs/redux-starter-kit/blob/master/type-tests/files/createSlice.typetest.ts#L84 I'd prefer the type was the actual literal, but that's just me. Cheers! |
We can't actually make the types true literals, because we're doing concatenation: Yeah, we don't have a real docs page on usage with TS, but the Advanced Tutorial page effectively covers that. |
Do you want to request a feature or report a bug?
(If this is a usage question, please do not post it here—post it on Stack Overflow instead. If this is not a “feature” or a “bug”, or the phrase “How do I...?” applies, then it's probably a usage question.)
What is the current behavior?
When you pass a
store
prop to aconnect
ed component, it attempts to use the value of the prop as a redux store. This is wreaking havoc on our codebase that hasstore
as a commonly passed prop. I haven't been able to find any documentation for this behavior and I can't find a way to override it, though it does seem to be intentional:https://github.com/reduxjs/react-redux/blob/master/src/components/connectAdvanced.js#L197
It even seems at one point there was a way to override this behavior:
https://github.com/reduxjs/react-redux/blob/master/src/components/connectAdvanced.js#L115
I'm filing this as a bug because as far as I can tell, #1000 removed this behavior and disabled the override key and then #1209 added it back in, without reenabling the override key. My guess is that this wasn't intentional and hope that adding the override key back would be acceptable.
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to a CodeSandbox (https://codesandbox.io/s/new) or RN Snack (https://snack.expo.io/) example below:
Repro is obvious, but I can add one if desired.
What is the expected behavior?
Either connect would not use the
store
prop at all, or the name would be overridable (likely preferred since it would be a less breaking change).Which versions of React, ReactDOM/React Native, Redux, and React Redux are you using? Which browser and OS are affected by this issue? Did this work in previous versions of React Redux?
react-redux 7.1.1
redux 4.0.4
react/react-dom 16.8.3
The text was updated successfully, but these errors were encountered: