Repository: reduxjs/react-redux (ts)

Issue:
connect assumes store prop is a redux store
**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](http://stackoverflow.com/questions/tagged/redux) 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 a `connect`ed component, it attempts to use the value of the prop as a redux store. This is wreaking havoc on our codebase that has `store` 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, https://github.com/reduxjs/react-redux/pull/1000 removed this behavior and disabled the override key and then https://github.com/reduxjs/react-redux/pull/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

Pull request description:
Pass non-Redux-store values through the `store` prop
Fixes #1393 , belatedly.

We've long had requests to allow passing through non-Redux store values as a prop named `store` for connected components.  With the v7 implementation, we can finally do something about that.

Patch:
diff --git a/docs/api/connect.md b/docs/api/connect.md
index 574af6b..3d6aa25 100644
--- a/docs/api/connect.md
+++ b/docs/api/connect.md
@@ -571,7 +571,7 @@ export default connect(
 
 The number of declared function parameters of `mapStateToProps` and `mapDispatchToProps` determines whether they receive `ownProps`
 
-> Note: `ownProps` is not passed to `mapStateToProps` and `mapDispatchToProps` if the formal definition of the function contains one mandatory parameter (function has length 1). For example, functions defined like below won't receive `ownProps` as the second argument. If the incoming value of `ownProps` is `undefined`, the default argument value will be  used.
+> Note: `ownProps` is not passed to `mapStateToProps` and `mapDispatchToProps` if the formal definition of the function contains one mandatory parameter (function has length 1). For example, functions defined like below won't receive `ownProps` as the second argument. If the incoming value of `ownProps` is `undefined`, the default argument value will be used.
 
 ```js
 function mapStateToProps(state) {
diff --git a/docs/api/hooks.md b/docs/api/hooks.md
index 8390ace..9ad3308 100644
--- a/docs/api/hooks.md
+++ b/docs/api/hooks.md
@@ -13,7 +13,6 @@ React Redux now offers a set of hook APIs as an alternative to the existing `con
 
 These hooks were first added in v7.1.0.
 
-
 ## Using Hooks in a React Redux App
 
 As with `connect()`, you should start by wrapping your entire application in a `<Provider>` component to make the store available throughout the component tree:
@@ -212,10 +211,6 @@ export const App = () => {
 
 ## Removed: `useActions()`
 
-
-
-
-
 ## `useDispatch()`
 
 ```js
@@ -295,7 +290,6 @@ export const CounterComponent = ({ value }) => {
 }
 ```
 
-
 ## Custom context
 
 The `<Provider>` component allows you to specify an alternate context via the `context` prop. This is useful if you're building a complex reusable component, and you don't want your store to collide with any Redux store your consumers' applications might use.
@@ -395,7 +389,7 @@ This hook was in our original alpha release, but removed in `v7.1.0-alpha.4`, ba
 That suggestion was based on "binding action creators" not being as useful in a hooks-based use case, and causing too
 much conceptual overhead and syntactic complexity.
 
-You should probably prefer to  call the [`useDispatch`](#usedispatch) hook in your components to retrieve a reference to `dispatch`,
+You should probably prefer to call the [`useDispatch`](#usedispatch) hook in your components to retrieve a reference to `dispatch`,
 and manually call `dispatch(someActionCreator())` in callbacks and effects as needed. You may also use the Redux
 [`bindActionCreators`](https://redux.js.org/api/bindactioncreators) function in your own code to bind action creators,
 or "manually" bind them like `const boundAddTodo = (text) => dispatch(addTodo(text))`.
@@ -410,12 +404,15 @@ import { useMemo } from 'react'
 
 export function useActions(actions, deps) {
   const dispatch = useDispatch()
-  return useMemo(() => {
-    if (Array.isArray(actions)) {
-      return actions.map(a => bindActionCreators(a, dispatch))
-    }
-    return bindActionCreators(actions, dispatch)
-  }, deps ? [dispatch, ...deps] : [dispatch])
+  return useMemo(
+    () => {
+      if (Array.isArray(actions)) {
+        return actions.map(a => bindActionCreators(a, dispatch))
+      }
+      return bindActionCreators(actions, dispatch)
+    },
+    deps ? [dispatch, ...deps] : [dispatch]
+  )
 }
 ```
 
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md
index cbecafa..ab8f7f2 100644
--- a/docs/troubleshooting.md
+++ b/docs/troubleshooting.md
@@ -118,4 +118,4 @@ Or by setting it globally:
 }
 ```
 
-See https://github.com/facebook/react/issues/14927#issuecomment-490426131
\ No newline at end of file
+See https://github.com/facebook/react/issues/14927#issuecomment-490426131
diff --git a/src/components/connectAdvanced.js b/src/components/connectAdvanced.js
index 94cf101..dcb18db 100644
--- a/src/components/connectAdvanced.js
+++ b/src/components/connectAdvanced.js
@@ -163,8 +163,14 @@ export default function connectAdvanced(
       // Retrieve the store and ancestor subscription via context, if available
       const contextValue = useContext(ContextToUse)
 
-      // The store _must_ exist as either a prop or in context
-      const didStoreComeFromProps = Boolean(props.store)
+      // The store _must_ exist as either a prop or in context.
+      // We'll check to see if it _looks_ like a Redux store first.
+      // This allows us to pass through a `store` prop that is just a plain value.
+      console.log('Store from props: ', props.store)
+      const didStoreComeFromProps =
+        Boolean(props.store) &&
+        Boolean(props.store.getState) &&
+        Boolean(props.store.dispatch)
       const didStoreComeFromContext =
         Boolean(contextValue) && Boolean(contextValue.store)
 
@@ -176,7 +182,8 @@ export default function connectAdvanced(
           `React context consumer to ${displayName} in connect options.`
       )
 
-      const store = props.store || contextValue.store
+      // Based on the previous check, one of these must be true
+      const store = didStoreComeFromProps ? props.store : contextValue.store
 
       const childPropsSelector = useMemo(() => {
         // The child props selector needs the store reference as an input.


Test patch:
diff --git a/test/components/connect.spec.js b/test/components/connect.spec.js
index 29d6da6..f9c5278 100644
--- a/test/components/connect.spec.js
+++ b/test/components/connect.spec.js
@@ -2090,6 +2090,21 @@ describe('React', () => {
         expect(actualState).toEqual(expectedState)
       })
 
+      it('should pass through a store prop that is not actually a Redux store', () => {
+        const notActuallyAStore = 42
+
+        const store = createStore(() => 123)
+        const Decorated = connect(state => ({ state }))(Passthrough)
+
+        const rendered = rtl.render(
+          <ProviderMock store={store}>
+            <Decorated store={notActuallyAStore} />
+          </ProviderMock>
+        )
+
+        expect(rendered.getByTestId('store')).toHaveTextContent('42')
+      })
+
       it('should pass through ancestor subscription when store is given as a prop', () => {
         const c3Spy = jest.fn()
         const c2Spy = jest.fn()