Browse Source

Combine basic examples

main
Alex Krolick 7 years ago
parent
commit
6eb29a18f5
  1. 14
      content/docs/context.md
  2. 47
      examples/context/motivation-problem.js
  3. 58
      examples/context/motivation-solution.js
  4. 28
      examples/context/theme-detailed-app.js
  5. 55
      examples/context/theme-example.js

14
content/docs/context.md

@ -8,7 +8,7 @@ Context provides a way to pass data through the component tree without having to
In a typical React application, data is passed top-down (parent to child) via props, but this can be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required by many components within an application. Context provides a way to share values like this between components without having to explicitly pass a prop through every level of the tree.
- [Motivation](#motivation)
- [When to Use Context](#when-to-use-context)
- [API](#api)
- [React.createContext](#reactcreatecontext)
- [Provider](#provider)
@ -22,9 +22,9 @@ In a typical React application, data is passed top-down (parent to child) via pr
- [Legacy API](#legacy-api)
## Motivation
## When to Use Context
Context is designed to relieve the pain of passing props down through a deeply nested component tree. For example, in the code below we manually thread through a color prop in order to style the Button and Message components:
Context is designed to share data that can be considered "global" for a tree of React components, such as the current authenticated user, theme, or preferred language. For example, in the code below we manually thread through a "theme" prop in order to style the Button component:
`embed:context/motivation-problem.js`
@ -32,6 +32,7 @@ Using context, we can avoid passing props through intermediate elements:
`embed:context/motivation-solution.js`
Note: Don't use context just to avoid passing props a few levels down.
## API
### `React.createContext`
@ -72,12 +73,6 @@ Requires a [function as a child](/docs/render-props.html#using-props-other-than-
## Examples
### Static Context
Here is an example illustrating how you might inject a "theme" using context:
`embed:context/theme-example.js`
### Dynamic Context
A more complex example with dynamic values for the theme:
@ -108,3 +103,4 @@ A more complex example with dynamic values for the theme:
> The old context API was marked as legacy in React 16.3 and will be removed in version 17.
>
> React previously shipped with an experimental context API. The old API will be supported in all 16.x releases, but applications using it should migrate to the new version. Read the [legacy context docs here](/docs/legacy-context.html).

47
examples/context/motivation-problem.js

@ -1,34 +1,23 @@
class Button extends React.Component {
render() {
return (
<button style={{background: this.props.color}}>
{this.props.children}
</button>
);
}
}
const ThemedButton = props => {
//highlight-range{1}
return <Button theme={props.theme} />;
};
class Message extends React.Component {
render() {
// highlight-range{1-3}
// The Message component must take `color` as as prop to pass it
// to the Button. Using context, the Button could connect to the
// color context on its own.
return (
<div>
<p>{this.props.text}</p>
<Button color={this.props.color}>Delete</Button>
</div>
);
}
}
// An intermediate component
const Toolbar = props => {
// highlight-range{1-2,5}
// The Toolbar component must take an extra theme prop
// and pass it to the ThemedButton
return (
<div>
<ThemedButton theme={props.theme} />
</div>
);
};
class MessageList extends React.Component {
class App extends React.Component {
render() {
const color = 'purple';
const children = this.props.messages.map(message => (
<Message text={message.text} color={color} />
));
return <div>{children}</div>;
// highlight-range{1}
return <Toolbar theme="dark" />;
}
}

58
examples/context/motivation-solution.js

@ -1,43 +1,31 @@
// highlight-range{1}
const ColorContext = React.createContext();
// Create a theme context, defaulting to light theme
// highlight-next-line
const ThemeContext = React.createContext('light');
class Button extends React.Component {
render() {
// highlight-range{2-8}
return (
<ColorContext.Consumer>
{color => (
<button style={{background: color}}>
{this.props.children}
</button>
)}
</ColorContext.Consumer>
);
}
}
// highlight-range{1,3-5}
// The ThemedButton receives the theme from context
const ThemedButton = props => (
<ThemeContext.Consumer>
{theme => <Button theme={theme} />}
</ThemeContext.Consumer>
);
class Message extends React.Component {
render() {
return (
<div>
<p>{this.props.text}</p>
<Button>Delete</Button>
</div>
);
}
}
// An intermediate component
const Toolbar = props => {
return (
<div>
<ThemedButton />
</div>
);
};
class MessageList extends React.Component {
class App extends React.Component {
render() {
const color = 'purple';
const children = this.props.messages.map(message => (
<Message text={message.text} />
));
// highlight-range{2-4}
// highlight-range{2,4}
return (
<ColorContext.Provider value={color}>
{children}
</ColorContext.Provider>
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}

28
examples/context/theme-detailed-app.js

@ -1,6 +1,15 @@
import {ThemeContext, themes} from './theme-context';
import ThemedButton from './button';
// An intermediate component that uses the ThemedButton
const Toolbar = props => {
return (
<ThemedButton onClick={props.changeTheme}>
Change Theme
</ThemedButton>
);
};
class App extends React.Component {
state = {
theme: themes.light,
@ -16,13 +25,20 @@ class App extends React.Component {
};
render() {
//highlight-range{2,6}
//highlight-range{1-3}
// The ThemedButton button inside the ThemeProvider
// uses the theme from state while the one outside uses
// the default dark theme
//highlight-range{3-5,7}
return (
<ThemeContext.Provider value={this.state.theme}>
<ThemedButton onClick={this.toggleTheme}>
Change Theme
</ThemedButton>
</ThemeContext.Provider>
<div>
<ThemeContext.Provider value={this.state.theme}>
<Toolbar changeTheme={this.toggleTheme} />
</ThemeContext.Provider>
<div>
<ThemedButton />
</div>
</div>
);
}
}

55
examples/context/theme-example.js

@ -1,55 +0,0 @@
// Create a theme context, defaulting to light theme
// highlight-next-line
const ThemeContext = React.createContext('light');
class ThemeProvider extends React.Component {
render() {
// highlight-range{2-4}
return (
<ThemeContext.Provider value={this.props.theme}>
{this.props.children}
</ThemeContext.Provider>
);
}
}
class ThemedButton extends React.Component {
render() {
//highlight-range{2-4}
return (
<ThemeContext.Consumer>
{theme => <Button theme={theme} />}
</ThemeContext.Consumer>
);
}
}
const SomeComponent = props => {
// The ThemedButton receives the theme from context;
// SomeComponent does not need to know about it
// highlight-range{3}
return (
<div>
<ThemedButton />
</div>
);
};
class App extends React.Component {
render() {
// The ThemedButton button inside the ThemeProvider
// uses the dark theme while the one outside uses the
// default light theme
// highlight-range{3-5,7}
return (
<div>
<ThemeProvider theme="dark">
<SomeComponent />
</ThemeProvider>
<div>
<ThemedButton />
</div>
</div>
);
}
}
Loading…
Cancel
Save