Browse Source

Added context HOC example to reference

main
Brian Vaughn 7 years ago
parent
commit
bd06bbc1a7
  1. 20
      content/docs/context.md
  2. 10
      examples/context/higher-order-component-before.js
  3. 7
      examples/context/higher-order-component-usage.js
  4. 18
      examples/context/higher-order-component.js

20
content/docs/context.md

@ -14,10 +14,10 @@ In a typical React application, data is passed top-down (parent to child) via pr
- [Provider](#provider)
- [Consumer](#consumer)
- [Examples](#examples)
- [Static Context](#static-context)
- [Dynamic Context](#dynamic-context)
- [Consuming Multiple Contexts](#consuming-multiple-contexts)
- [Accessing Context in Lifecycle Methods](#accessing-context-in-lifecycle-methods)
- [Consuming Context with a HOC](#consuming-context-with-a-hoc)
- [Forwarding Refs to Context Consumers](#forwarding-refs-to-context-consumers)
- [Caveats](#caveats)
- [Legacy API](#legacy-api)
@ -104,6 +104,24 @@ Accessing values from context in lifecycle methods is a relatively common use ca
`embed:context/lifecycles.js`
### Consuming Context with a HOC
Some types of contexts are consumed by many components (e.g. theme or localization). It can be tedious to explicitly wrap each dependency with a `<Context.Consumer>` element. A [higher-order component](/docs/higher-order-components.html) can help with this.
For example, a button component might consume a theme context like so:
`embed:context/higher-order-component-before.js`
That's alright for a few components, but what if we wanted to use the theme context in a lot of places?
We could create a higher-order component called `withTheme`:
`embed:context/higher-order-component.js`
Now any component that depends on the theme context can easy subscribe to it using the `withTheme` function we've created:
`embed:context/higher-order-component-usage.js`
### Forwarding Refs to Context Consumers
One issue with the render prop API is that refs don't automatically get passed to wrapped elements. To get around this, use `React.forwardRef`:

10
examples/context/higher-order-component-before.js

@ -0,0 +1,10 @@
const ThemeContext = React.createContext('light');
function ThemedButton(props) {
// highlight-range{2-4}
return (
<ThemeContext.Consumer>
{theme => <button className={theme} {...props} />}
</ThemeContext.Consumer>
);
}

7
examples/context/higher-order-component-usage.js

@ -0,0 +1,7 @@
function Button({theme, ...rest}) {
// highlight-next-line
return <button className={theme} {...rest} />;
}
// highlight-next-line
const ThemedButton = withTheme(Button);

18
examples/context/higher-order-component.js

@ -0,0 +1,18 @@
const ThemeContext = React.createContext('light');
// This function takes a component...
// highlight-next-line
export function withTheme(Component) {
// ...and returns another component...
// highlight-next-line
return function ThemedComponent(props) {
// ... and renders the wrapped component with the context theme!
// Notice that we pass through any additional props as well
// highlight-range{2-4}
return (
<ThemeContext.Consumer>
{theme => <Component {...props} theme={theme} />}
</ThemeContext.Consumer>
);
};
}
Loading…
Cancel
Save