Skip to content

Commit 691cd45

Browse files
committed
Added inline child function caveat to Context docs
1 parent 28b2b76 commit 691cd45

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

content/docs/context.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ Accepts a `value` prop to be passed to Consumers that are descendants of this Pr
6969

7070
A React component that subscribes to context changes.
7171

72-
Requires a [function as a child](/docs/render-props.html#using-props-other-than-render). The function receives the current context value and returns a React node. All consumers are re-rendered whenever the Provider value changes. Changes are determined by comparing the new and old values using the same algorithm as [`Object.is`](developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description). (This can cause some issues when passing objects as `value`: see [Caveats](#caveats).)
72+
Requires a [function as a child](/docs/render-props.html#using-props-other-than-render). The function receives the current context value and returns a React node. The function should be created inline, as shown in the example above, rather than being bound to the instance or otherwise cached. (Refer to the see [Caveats](#consumer-inline-function-as-a-child) section below for more.)
73+
74+
All consumers are re-rendered whenever the Provider value changes. Changes are determined by comparing the new and old values using the same algorithm as [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description). (This can cause some issues when passing objects as `value`: see [Caveats](#objectis).)
7375

7476
> Note
7577
>
@@ -134,6 +136,16 @@ One issue with the render prop API is that refs don't automatically get passed t
134136

135137
## Caveats
136138

139+
### `Consumer` Inline Function as a Child
140+
141+
As an optimization to avoid doing unnecessary work, React currently stops rendering when it sees children that are equal to the most recently rendered children. This applies to the [function as a child](/docs/render-props.html#using-props-other-than-render) pattern used by `Consumer` as well which can cause unexpected behavior in some situations:
142+
`embed:context/consumer-cached-function-as-a-child.js`
143+
144+
To avoid this scenario, we recommend declaring the child function inline:
145+
`embed:context/consumer-inline-function-as-a-child.js`
146+
147+
### `Object.is`
148+
137149
Because context uses reference identity to determine when to re-render, there are some gotchas that could trigger unintentional renders in consumers when a provider's parent re-renders. For example, the code below will re-render all consumers every time the Provider re-renders because a new object is always created for `value`:
138150

139151
`embed:context/reference-caveats-problem.js`
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Example extends React.Component {
2+
// This method will be called when the context value changes,
3+
// But not when the props value changes!
4+
renderValue = value => {
5+
return (
6+
<div>
7+
Context value:{value}. Props value:{this.props.counter}
8+
</div>
9+
);
10+
};
11+
12+
render() {
13+
return <Ctx.Consumer>{this.renderValue}</Ctx.Consumer>;
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Example extends React.Component {
2+
render() {
3+
// The inline function will be called when the context value changes,
4+
// And when the props value changes!
5+
return (
6+
<Ctx.Consumer>
7+
{value => (
8+
<div>
9+
Context value:{value}. Props value:{this.props.counter}
10+
</div>
11+
)}
12+
</Ctx.Consumer>
13+
);
14+
}
15+
}

0 commit comments

Comments
 (0)