Skip to content

Commit 8f52e1f

Browse files
kevin940726Michael Jackson
authored andcommitted
fix nested provider bug with getter function
1 parent 454cb22 commit 8f52e1f

File tree

2 files changed

+93
-2
lines changed

2 files changed

+93
-2
lines changed

modules/__tests__/createContext-test.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,90 @@ describe("A <Consumer>", () => {
132132
});
133133
});
134134
});
135+
136+
describe("nested <Provider>", () => {
137+
let node;
138+
beforeEach(() => {
139+
node = document.createElement("div");
140+
});
141+
142+
it("gets the updated broadcast value as it changes", done => {
143+
const ParentContext = createContext("cupcakes");
144+
const ChildContext = createContext();
145+
146+
class UpdateBlocker extends React.Component {
147+
shouldComponentUpdate() {
148+
return false;
149+
}
150+
151+
render() {
152+
return this.props.children;
153+
}
154+
}
155+
156+
class AsyncRender extends React.Component {
157+
state = {
158+
shouldRender: false
159+
};
160+
161+
componentDidMount() {
162+
// simulate asynchronous rendering
163+
setTimeout(() => {
164+
this.setState({
165+
shouldRender: true
166+
});
167+
});
168+
}
169+
170+
render() {
171+
return this.state.shouldRender && this.props.children;
172+
}
173+
}
174+
175+
class Parent extends React.Component {
176+
state = {
177+
value: ParentContext.Provider.defaultValue
178+
};
179+
180+
render() {
181+
return (
182+
<ParentContext.Provider value={this.state.value}>
183+
<button
184+
onClick={() => this.setState({ value: "bubblegum" })}
185+
ref={node => (this.button = node)}
186+
/>
187+
<UpdateBlocker>
188+
<ChildContext.Provider>
189+
<AsyncRender>
190+
<Child />
191+
</AsyncRender>
192+
</ChildContext.Provider>
193+
</UpdateBlocker>
194+
</ParentContext.Provider>
195+
);
196+
}
197+
}
198+
199+
let childDidRender = false;
200+
201+
class Child extends React.Component {
202+
render() {
203+
return (
204+
<ParentContext.Consumer
205+
children={value => {
206+
expect(value).toBe("bubblegum");
207+
208+
done();
209+
210+
return null;
211+
}}
212+
/>
213+
);
214+
}
215+
}
216+
217+
ReactDOM.render(<Parent />, node, function() {
218+
Simulate.click(this.button);
219+
});
220+
});
221+
});

modules/createContext.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,17 @@ function createContext(defaultValue) {
6464
};
6565
};
6666

67+
getValue = () => {
68+
return this.props.value;
69+
};
70+
6771
getChildContext() {
6872
return {
6973
broadcasts: {
7074
...this.context.broadcasts,
7175
[channel]: {
7276
subscribe: this.subscribe,
73-
value: this.props.value
77+
getValue: this.getValue
7478
}
7579
}
7680
};
@@ -108,7 +112,7 @@ function createContext(defaultValue) {
108112
broadcast = this.context.broadcasts && this.context.broadcasts[channel];
109113

110114
state = {
111-
value: this.broadcast ? this.broadcast.value : defaultValue
115+
value: this.broadcast ? this.broadcast.getValue() : defaultValue
112116
};
113117

114118
componentDidMount() {

0 commit comments

Comments
 (0)