From b0e2b5b495e66929b9812c320500a843103d7137 Mon Sep 17 00:00:00 2001 From: Anton Korzunov Date: Fri, 18 May 2018 22:01:24 +1000 Subject: [PATCH] fix: Context Provider could crash update, #944 --- .../src/components/App.js | 22 +++++++++++++++++++ .../src/components/Counter.js | 22 +++++++++++++++++++ src/reconciler/hotReplacementRender.js | 8 ++++++- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 examples/all-possible-containers/src/components/Counter.js diff --git a/examples/all-possible-containers/src/components/App.js b/examples/all-possible-containers/src/components/App.js index 30a2ec9bb..4c7164df4 100644 --- a/examples/all-possible-containers/src/components/App.js +++ b/examples/all-possible-containers/src/components/App.js @@ -1,6 +1,9 @@ // @flow import React from 'react' +import Context from '../context' +import Counter from './Counter' + import ErrorBoundary from './ErrorBoundary' import ModalComponent from './ModalComponent' @@ -16,6 +19,16 @@ import ConnectedChildrenAFComponent from './ConnectedChildrenAFComponent' import FunctionConsumerPureClassComponent from './FunctionConsumerPureClassComponent' import { EDIT_ME } from './_editMe' +const Secret = (() => { + const A = () => ( +
+ component A +
+ ) + const B = () => 'wrong' + return { A, B } +})() + class App extends React.Component { state = { error: null, @@ -32,6 +45,7 @@ class App extends React.Component { render() { const { open, error, errorInfo } = this.state + const { A, B } = Secret return error ? ( @@ -60,6 +74,14 @@ class App extends React.Component { onRequestClose={() => this.setState({ open: false })} /> )} +
+ + + {value => (value === '42' ? : )} + + + +
) diff --git a/examples/all-possible-containers/src/components/Counter.js b/examples/all-possible-containers/src/components/Counter.js new file mode 100644 index 000000000..bee462743 --- /dev/null +++ b/examples/all-possible-containers/src/components/Counter.js @@ -0,0 +1,22 @@ +import React from 'react' + +class Counter extends React.Component { + state = { count: 0 } + + componentDidMount() { + this.interval = setInterval( + () => this.setState(prevState => ({ count: prevState.count + 1 })), + 200, + ) + } + + componentWillUnmount() { + clearInterval(this.interval) + } + + render() { + return
#{this.state.count}
+ } +} + +export default Counter diff --git a/src/reconciler/hotReplacementRender.js b/src/reconciler/hotReplacementRender.js index b77710752..a0c9e62de 100644 --- a/src/reconciler/hotReplacementRender.js +++ b/src/reconciler/hotReplacementRender.js @@ -338,7 +338,13 @@ const hotReplacementRender = (instance, stack) => { if (isContextProvider(child)) { extraContext = new Map(extraContext) - extraContext.set(getContextProvider(child.type), child.props.value) + extraContext.set( + getContextProvider(child.type), + { + ...(child.nextProps || {}), + ...(child.props || {}), + }.value, + ) childName = 'ContextProvider' }