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. 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) - [API](#api)
- [React.createContext](#reactcreatecontext) - [React.createContext](#reactcreatecontext)
- [Provider](#provider) - [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) - [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` `embed:context/motivation-problem.js`
@ -32,6 +32,7 @@ Using context, we can avoid passing props through intermediate elements:
`embed:context/motivation-solution.js` `embed:context/motivation-solution.js`
Note: Don't use context just to avoid passing props a few levels down.
## API ## API
### `React.createContext` ### `React.createContext`
@ -72,12 +73,6 @@ Requires a [function as a child](/docs/render-props.html#using-props-other-than-
## Examples ## Examples
### Static Context
Here is an example illustrating how you might inject a "theme" using context:
`embed:context/theme-example.js`
### Dynamic Context ### Dynamic Context
A more complex example with dynamic values for the theme: 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. > 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). > 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 { const ThemedButton = props => {
render() { //highlight-range{1}
return ( return <Button theme={props.theme} />;
<button style={{background: this.props.color}}> };
{this.props.children}
</button>
);
}
}
class Message extends React.Component { // An intermediate component
render() { const Toolbar = props => {
// highlight-range{1-3} // highlight-range{1-2,5}
// The Message component must take `color` as as prop to pass it // The Toolbar component must take an extra theme prop
// to the Button. Using context, the Button could connect to the // and pass it to the ThemedButton
// color context on its own. return (
return ( <div>
<div> <ThemedButton theme={props.theme} />
<p>{this.props.text}</p> </div>
<Button color={this.props.color}>Delete</Button> );
</div> };
);
}
}
class MessageList extends React.Component { class App extends React.Component {
render() { render() {
const color = 'purple'; // highlight-range{1}
const children = this.props.messages.map(message => ( return <Toolbar theme="dark" />;
<Message text={message.text} color={color} />
));
return <div>{children}</div>;
} }
} }

58
examples/context/motivation-solution.js

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

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

@ -1,6 +1,15 @@
import {ThemeContext, themes} from './theme-context'; import {ThemeContext, themes} from './theme-context';
import ThemedButton from './button'; 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 { class App extends React.Component {
state = { state = {
theme: themes.light, theme: themes.light,
@ -16,13 +25,20 @@ class App extends React.Component {
}; };
render() { 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 ( return (
<ThemeContext.Provider value={this.state.theme}> <div>
<ThemedButton onClick={this.toggleTheme}> <ThemeContext.Provider value={this.state.theme}>
Change Theme <Toolbar changeTheme={this.toggleTheme} />
</ThemedButton> </ThemeContext.Provider>
</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