Skip to content

Ensure that component prop 'context' really contains a React context … #1134

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

Merged
merged 10 commits into from
Jan 8, 2019
9 changes: 6 additions & 3 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import nodeResolve from 'rollup-plugin-node-resolve'
import babel from 'rollup-plugin-babel'
import replace from 'rollup-plugin-replace'
import commonjs from 'rollup-plugin-commonjs'
import {uglify} from 'rollup-plugin-uglify'
import { uglify } from 'rollup-plugin-uglify'
import pkg from './package.json'

const env = process.env.NODE_ENV
Expand All @@ -22,14 +22,17 @@ const config = {
nodeResolve(),
babel({
exclude: '**/node_modules/**',
runtimeHelpers: true,
runtimeHelpers: true
}),
replace({
'process.env.NODE_ENV': JSON.stringify(env)
}),
commonjs({
namedExports: {
'node_modules/react-is/index.js': ['isValidElementType'],
'node_modules/react-is/index.js': [
'isValidElementType',
'isContextConsumer'
]
}
})
]
Expand Down
9 changes: 7 additions & 2 deletions src/components/connectAdvanced.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import hoistStatics from 'hoist-non-react-statics'
import invariant from 'invariant'
import React, { Component, PureComponent } from 'react'
import { isValidElementType } from 'react-is'
import { isValidElementType, isContextConsumer } from 'react-is'

import { ReactReduxContext } from './Context'

Expand Down Expand Up @@ -213,7 +213,12 @@ export default function connectAdvanced(
}

render() {
const ContextToUse = this.props.context || Context
const ContextToUse =
this.props.context &&
this.props.context.Consumer &&
isContextConsumer(<this.props.context.Consumer />)
? this.props.context
: Context

return (
<ContextToUse.Consumer>
Expand Down
30 changes: 30 additions & 0 deletions test/components/connect.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1564,6 +1564,36 @@ describe('React', () => {
expect(actualState).toEqual(expectedState)
})

it('should ignore non-react-context values that are passed as a prop to the component', () => {
class Container extends Component {
render() {
return <Passthrough />
}
}

const nonContext = { someProperty: {} }

let actualState

const expectedState = { foos: {} }

const decorator = connect(state => {
actualState = state
return {}
})
const Decorated = decorator(Container)

const store = createStore(() => expectedState)

rtl.render(
<ProviderMock store={store}>
<Decorated context={nonContext} />
</ProviderMock>
)

expect(actualState).toEqual(expectedState)
})

it('should throw an error if the store is not in the props or context', () => {
const spy = jest.spyOn(console, 'error').mockImplementation(() => {})

Expand Down