September 2018
Powering Code Reuse

with Context and Render Props
Forbes Lindesay
Thanks to our sponsors!
FUNCTIONS AS FIRST
CLASS VALUES
DOUBLE/TRIPPLE ARRAY
function doubleArr(vs) {
const result = [];
for (let i=0;i<vs.length;i ++) {
result.push(vs[i] * 2);
}
return result;
}
// input: [1, 2, 3]
// output: [2, 4, 6]
function trippleArr(vs) {
const result = [];
for (let i=0;i<vs.length;i ++) {
result.push(vs[i] * 3);
}
return result;
}
// input: [1, 2, 3]
// output: [3, 6, 9]
function trippleArr(vs) {
const result = [];
for (let i=0;i<vs.length;i ++) {
result.push(vs[i] * 3);
}
return result;
}
// input: [1, 2, 3]
// output: [3, 6, 9]
function doubleArr(vs) {
const result = [];
for (let i=0;i<vs.length;i ++) {
result.push(vs[i] * 2);
}
return result;
}
// input: [1, 2, 3]
// output: [2, 4, 6]
DOUBLE/TRIPPLE ARRAY
function multiplyArr(vs, factor) {
const result = [];
for (let i=0;i<vs.length;i ++) {
result.push(vs[i] * factor);
}
return result;
}
MULTIPLY ARRAY
MULTIPLY/ADD ARRAY
function multiplyArr(vs, factor) {
const result = [];
for (let i=0;i<vs.length;i ++) {
result.push(vs[i] * factor);
}
return result;
}
// input: [1, 2, 3], 3
// output: [3, 6, 9]
function addArr(vs, increment) {
const result = [];
for (let i=0;i<vs.length;i ++) {
result.push(vs[i] + increment);
}
return result;
}
// input: [1, 2, 3], 3
// output: [4, 5, 6]
function multiplyArr(vs, factor) {
const result = [];
for (let i=0;i<vs.length;i ++) {
result.push(vs[i] * factor);
}
return result;
}
// input: [1, 2, 3], 3
// output: [3, 6, 9]
function addArr(vs, increment) {
const result = [];
for (let i=0;i<vs.length;i ++) {
result.push(vs[i] + increment);
}
return result;
}
// input: [1, 2, 3], 3
// output: [4, 5, 6]
MULTIPLY/ADD ARRAY
function mapArray(vs, fn) {
const result = [];
for (let i=0;i<vs.length;i ++) {
result.push(fn(vs[i]));
}
return result;
}
MAP ARRAY
MAP ARRAY
function mapArray(vs, fn) {
return vs.map(fn);
}
REACT PROPERTIES
ARE PARAMETERS
REACT NOW
class Now extends React.Component {
state = {now: new Date()};
componentDidMount() {
this._timer = setInterval(
() => this.setState({now: new Date()}),
100,
);
}
componentWillUnmount() {
clearInterval(this._timer);
}
render() {
return this.state.now.toString();
}
}
REACT NOW
class UTCNow extends React.Component {
state = {now: new Date()};
componentDidMount() {
this._timer = setInterval(
() => this.setState({now: new Date()}),
100,
);
}
componentWillUnmount() {
clearInterval(this._timer);
}
render() {
return this.state.now.toUTCString();
}
}
class UTCNow extends React.Component {
state = {now: new Date()};
componentDidMount() {
this._timer = setInterval(
() => this.setState({now: new Date()}),
100,
);
}
componentWillUnmount() {
clearInterval(this._timer);
}
render() {
return this.state.now.toUTCString();
}
}
REACT NOW
REACT NOW
class Now extends React.Component {
state = {now: new Date()};
componentDidMount() {
this._timer = setInterval(
() => this.setState({now: new Date()}),
100,
);
}
componentWillUnmount() {
clearInterval(this._timer);
}
render() {
return this.state.now.[
this.props.utc ? 'toUTCString' : 'toString'
]();
}
}
REACT NOW
class Now extends React.Component {
state = {now: new Date()};
componentDidMount() {
this._timer = setInterval(
() => this.setState({now: new Date()}),
100,
);
}
componentWillUnmount() {
clearInterval(this._timer);
}
render() {
return this.props.render(this.state.now);
}
}
REACT NOW
function LocalTime() {
return <Now render={now => now.toTimeString()} />;
}
function UTCTime() {
return <Now render={now => now.toUTCTimeString()} />;
}
function LocalDateTime() {
return <Now render={now => now.toString()} />;
}
function UTCDateTime() {
return <Now render={now => now.toUTCString()} />;
}
DATE FORMATTING
Fri Sep 14 2018 15:47:26 GMT+0200 (Central European
Summer Time)
<strong>Fri Sep 14 2018 </strong> 15:47:26
GMT+0200 (Central European Summer Time)
REACT NOW
function DateTime() {
return (
<Now render={now => (
<React.Fragment>
<strong>{now.toDateString()} </strong>
{' ' + now.toTimeString()}
</React.Fragment>
)} />
);
}
“CHILDREN” IS JUST
A SPECIAL PROPERTY
REACT NOW
class Now extends React.Component {
state = {now: new Date()};
componentDidMount() {
this._timer = setInterval(
() => this.setState({now: new Date()}),
100,
);
}
componentWillUnmount() {
clearInterval(this._timer);
}
render() {
return this.props.render(this.state.now);
}
}
REACT NOW
class Now extends React.Component {
state = {now: new Date()};
componentDidMount() {
this._timer = setInterval(
() => this.setState({now: new Date()}),
100,
);
}
componentWillUnmount() {
clearInterval(this._timer);
}
render() {
return this.props.children(this.state.now);
}
}
function DateTime() {
return (
<Now render={now => (
<React.Fragment>
<strong>{now.toDateString()} </strong>
{' ' + now.toTimeString()}
</React.Fragment>
)} />
);
}
REACT NOW
REACT NOW
function DateTime() {
return (
<Now>
{now => (
<React.Fragment>
<strong>{now.toDateString()} </strong>
{' ' + now.toTimeString()}
</React.Fragment>
)}
</Now>
);
}
STATE IS ANYTHING THAT
CHANGES OVER TIME
REACT TREE
COMPONENT
COMPONENT COMPONENT
COMPONENT COMPONENTCOMPONENTCOMPONENT
COMPONENT COMPONENT COMPONENT COMPONENTCOMPONENTCOMPONENT
REACT TREE
COMPONENT
COMPONENT COMPONENT
COMPONENT COMPONENTCOMPONENTCOMPONENT
COMPONENT COMPONENT COMPONENT COMPONENTCOMPONENTA
REACT TREE
COMPONENT
COMPONENT COMPONENT
COMPONENT COMPONENTCOMPONENTCOMPONENT
COMPONENT COMPONENT COMPONENT COMPONENTBA
REACT TREE
COMPONENT
COMPONENT COMPONENT
PARENT COMPONENTCOMPONENTCOMPONENT
COMPONENT COMPONENT COMPONENT COMPONENTBA
REACT TREE
COMPONENT
COMPONENT COMPONENT
PARENT COMPONENTCOMPONENTCOMPONENT
COMPONENT C COMPONENT COMPONENTBA
REACT TREE
ROOT
COMPONENT COMPONENT
PARENT COMPONENTCOMPONENTCOMPONENT
COMPONENT C COMPONENT COMPONENTBA
REACT TREE
ROOT
COMPONENT COMPONENT
PARENT COMPONENTCOMPONENTCOMPONENT
COMPONENT C COMPONENT COMPONENTBA
REACT TREE
ROOT
COMPONENT COMPONENT
COMPONENT COMPONENTCOMPONENTCOMPONENT
COMPONENT C COMPONENT COMPONENTBA
External Store?
REACT TREE
ROOT
COMPONENT COMPONENT
COMPONENT COMPONENTCOMPONENTCOMPONENT
COMPONENT C COMPONENT COMPONENTBA
REACT TREE
ROOT
COMPONENT COMPONENT
COMPONENT COMPONENTCOMPONENTCOMPONENT
COMPONENT C COMPONENT COMPONENTBA
REACT TREE
ROOT
SHARED
PARENT COMPONENT
COMPONENT COMPONENTCOMPONENT
C
COMPONENT
COMPONENT COMPONENT COMPONENTBA
REACT TREE
ROOT
SHARED
PARENT COMPONENT
COMPONENT COMPONENT
C
COMPONENT
COMPONENT D EBA
SHARED
PARENT 2
const Color = React.createContext('black');
function ThemedCircle() {
return (
<Color.Consumer>
{color => <Circle color={color} />}
</Color.Consumer>
)
}
<React.Fragment>
<Color.Provider value="blue">
<ThemedCircle /><ThemedCircle /><ThemedCircle />
</Color.Provider>
<Color.Provider value="red">
<ThemedCircle /><ThemedCircle /><ThemedCircle />
</Color.Provider>
<ThemedCircle /><ThemedCircle /><ThemedCircle />
</React.Fragment>
const Color = React.createContext('black');
function ThemedCircle() {
return (
<Color.Consumer>
{color => <Circle color={color} />}
</Color.Consumer>
)
}
<React.Fragment>
<Color.Provider value="blue">
<ThemedCircle /><ThemedCircle /><ThemedCircle />
</Color.Provider>
<Color.Provider value="red">
<ThemedCircle /><ThemedCircle /><ThemedCircle />
</Color.Provider>
<ThemedCircle /><ThemedCircle /><ThemedCircle />
</React.Fragment>
const Color = React.createContext('black');
function ThemedCircle() {
return (
<Color.Consumer>
{color => <Circle color={color} />}
</Color.Consumer>
)
}
<React.Fragment>
<Color.Provider value="blue">
<ThemedCircle /><ThemedCircle /><ThemedCircle />
</Color.Provider>
<Color.Provider value="red">
<ThemedCircle /><ThemedCircle /><ThemedCircle />
</Color.Provider>
<ThemedCircle /><ThemedCircle /><ThemedCircle />
</React.Fragment>
const Toggle = React.createContext({on: false, onToggle: () => {}});
class ToggleProvider extends React.Component {
state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))};
render() {
return (
<Toggle.Provider value={this.state}>
{this.props.children}
</Toggle.Provider>
);
}
}
function ToggleButton() {
return (
<Toggle.Consumer>
{({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>}
</Toggle.Consumer>
)
}
<ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider>
const Toggle = React.createContext({on: false, onToggle: () => {}});
class ToggleProvider extends React.Component {
state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))};
render() {
return (
<Toggle.Provider value={this.state}>
{this.props.children}
</Toggle.Provider>
);
}
}
function ToggleButton() {
return (
<Toggle.Consumer>
{({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>}
</Toggle.Consumer>
)
}
<ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider>
const Toggle = React.createContext({on: false, onToggle: () => {}});
class ToggleProvider extends React.Component {
state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))};
render() {
return (
<Toggle.Provider value={this.state}>
{this.props.children}
</Toggle.Provider>
);
}
}
function ToggleButton() {
return (
<Toggle.Consumer>
{({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>}
</Toggle.Consumer>
)
}
<ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider>
const Toggle = React.createContext({on: false, onToggle: () => {}});
class ToggleProvider extends React.Component {
state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))};
render() {
return (
<Toggle.Provider value={this.state}>
{this.props.children}
</Toggle.Provider>
);
}
}
function ToggleButton() {
return (
<Toggle.Consumer>
{({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>}
</Toggle.Consumer>
)
}
<ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider>
OFF OFF OFF
const Toggle = React.createContext({on: false, onToggle: () => {}});
class ToggleProvider extends React.Component {
state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))};
render() {
return (
<Toggle.Provider value={this.state}>
{this.props.children}
</Toggle.Provider>
);
}
}
function ToggleButton() {
return (
<Toggle.Consumer>
{({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>}
</Toggle.Consumer>
)
}
<ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider>
ON ON ON
const Toggle = React.createContext({on: false, onToggle: () => {}});
class ToggleProvider extends React.Component {
state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))};
render() {
return (
<Toggle.Provider value={this.state}>
{this.props.children}
</Toggle.Provider>
);
}
}
function ToggleButton() {
return (
<Toggle.Consumer>
{({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>}
</Toggle.Consumer>
)
}
<ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider>
OFF OFF OFF
const Toggle = React.createContext({on: false, onToggle: () => {}});
class ToggleProvider extends React.Component {
state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))};
render() {
return (
<Toggle.Provider value={this.state}>
{this.props.children}
</Toggle.Provider>
);
}
}
function ToggleButton() {
return (
<Toggle.Consumer>
{({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>}
</Toggle.Consumer>
)
}
<ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider>
ON ON ON
SUMMARY
▸ Functions being first class values means we can use them as
parameters to enable more flexible code re-use
▸ Using functions as parameters allows highly customisable
shared components, complete with state and lifecycle hooks.
▸ React Context lets you share state across the tree of your
application
▸ Context still uses the React tree. This means it works with
server side rendering and you can safely use it in parts of your
app, as well as using it as a whole app solution.
@ForbesLindesay

Powering code reuse with context and render props

  • 1.
    September 2018 Powering CodeReuse with Context and Render Props Forbes Lindesay
  • 2.
    Thanks to oursponsors!
  • 3.
  • 4.
    DOUBLE/TRIPPLE ARRAY function doubleArr(vs){ const result = []; for (let i=0;i<vs.length;i ++) { result.push(vs[i] * 2); } return result; } // input: [1, 2, 3] // output: [2, 4, 6] function trippleArr(vs) { const result = []; for (let i=0;i<vs.length;i ++) { result.push(vs[i] * 3); } return result; } // input: [1, 2, 3] // output: [3, 6, 9]
  • 5.
    function trippleArr(vs) { constresult = []; for (let i=0;i<vs.length;i ++) { result.push(vs[i] * 3); } return result; } // input: [1, 2, 3] // output: [3, 6, 9] function doubleArr(vs) { const result = []; for (let i=0;i<vs.length;i ++) { result.push(vs[i] * 2); } return result; } // input: [1, 2, 3] // output: [2, 4, 6] DOUBLE/TRIPPLE ARRAY
  • 6.
    function multiplyArr(vs, factor){ const result = []; for (let i=0;i<vs.length;i ++) { result.push(vs[i] * factor); } return result; } MULTIPLY ARRAY
  • 7.
    MULTIPLY/ADD ARRAY function multiplyArr(vs,factor) { const result = []; for (let i=0;i<vs.length;i ++) { result.push(vs[i] * factor); } return result; } // input: [1, 2, 3], 3 // output: [3, 6, 9] function addArr(vs, increment) { const result = []; for (let i=0;i<vs.length;i ++) { result.push(vs[i] + increment); } return result; } // input: [1, 2, 3], 3 // output: [4, 5, 6]
  • 8.
    function multiplyArr(vs, factor){ const result = []; for (let i=0;i<vs.length;i ++) { result.push(vs[i] * factor); } return result; } // input: [1, 2, 3], 3 // output: [3, 6, 9] function addArr(vs, increment) { const result = []; for (let i=0;i<vs.length;i ++) { result.push(vs[i] + increment); } return result; } // input: [1, 2, 3], 3 // output: [4, 5, 6] MULTIPLY/ADD ARRAY
  • 9.
    function mapArray(vs, fn){ const result = []; for (let i=0;i<vs.length;i ++) { result.push(fn(vs[i])); } return result; } MAP ARRAY
  • 10.
    MAP ARRAY function mapArray(vs,fn) { return vs.map(fn); }
  • 11.
  • 12.
    REACT NOW class Nowextends React.Component { state = {now: new Date()}; componentDidMount() { this._timer = setInterval( () => this.setState({now: new Date()}), 100, ); } componentWillUnmount() { clearInterval(this._timer); } render() { return this.state.now.toString(); } }
  • 13.
    REACT NOW class UTCNowextends React.Component { state = {now: new Date()}; componentDidMount() { this._timer = setInterval( () => this.setState({now: new Date()}), 100, ); } componentWillUnmount() { clearInterval(this._timer); } render() { return this.state.now.toUTCString(); } }
  • 14.
    class UTCNow extendsReact.Component { state = {now: new Date()}; componentDidMount() { this._timer = setInterval( () => this.setState({now: new Date()}), 100, ); } componentWillUnmount() { clearInterval(this._timer); } render() { return this.state.now.toUTCString(); } } REACT NOW
  • 15.
    REACT NOW class Nowextends React.Component { state = {now: new Date()}; componentDidMount() { this._timer = setInterval( () => this.setState({now: new Date()}), 100, ); } componentWillUnmount() { clearInterval(this._timer); } render() { return this.state.now.[ this.props.utc ? 'toUTCString' : 'toString' ](); } }
  • 16.
    REACT NOW class Nowextends React.Component { state = {now: new Date()}; componentDidMount() { this._timer = setInterval( () => this.setState({now: new Date()}), 100, ); } componentWillUnmount() { clearInterval(this._timer); } render() { return this.props.render(this.state.now); } }
  • 17.
    REACT NOW function LocalTime(){ return <Now render={now => now.toTimeString()} />; } function UTCTime() { return <Now render={now => now.toUTCTimeString()} />; } function LocalDateTime() { return <Now render={now => now.toString()} />; } function UTCDateTime() { return <Now render={now => now.toUTCString()} />; }
  • 18.
    DATE FORMATTING Fri Sep14 2018 15:47:26 GMT+0200 (Central European Summer Time) <strong>Fri Sep 14 2018 </strong> 15:47:26 GMT+0200 (Central European Summer Time)
  • 19.
    REACT NOW function DateTime(){ return ( <Now render={now => ( <React.Fragment> <strong>{now.toDateString()} </strong> {' ' + now.toTimeString()} </React.Fragment> )} /> ); }
  • 20.
    “CHILDREN” IS JUST ASPECIAL PROPERTY
  • 21.
    REACT NOW class Nowextends React.Component { state = {now: new Date()}; componentDidMount() { this._timer = setInterval( () => this.setState({now: new Date()}), 100, ); } componentWillUnmount() { clearInterval(this._timer); } render() { return this.props.render(this.state.now); } }
  • 22.
    REACT NOW class Nowextends React.Component { state = {now: new Date()}; componentDidMount() { this._timer = setInterval( () => this.setState({now: new Date()}), 100, ); } componentWillUnmount() { clearInterval(this._timer); } render() { return this.props.children(this.state.now); } }
  • 23.
    function DateTime() { return( <Now render={now => ( <React.Fragment> <strong>{now.toDateString()} </strong> {' ' + now.toTimeString()} </React.Fragment> )} /> ); } REACT NOW
  • 24.
    REACT NOW function DateTime(){ return ( <Now> {now => ( <React.Fragment> <strong>{now.toDateString()} </strong> {' ' + now.toTimeString()} </React.Fragment> )} </Now> ); }
  • 25.
    STATE IS ANYTHINGTHAT CHANGES OVER TIME
  • 26.
    REACT TREE COMPONENT COMPONENT COMPONENT COMPONENTCOMPONENTCOMPONENTCOMPONENT COMPONENT COMPONENT COMPONENT COMPONENTCOMPONENTCOMPONENT
  • 27.
    REACT TREE COMPONENT COMPONENT COMPONENT COMPONENTCOMPONENTCOMPONENTCOMPONENT COMPONENT COMPONENT COMPONENT COMPONENTCOMPONENTA
  • 28.
    REACT TREE COMPONENT COMPONENT COMPONENT COMPONENTCOMPONENTCOMPONENTCOMPONENT COMPONENT COMPONENT COMPONENT COMPONENTBA
  • 29.
    REACT TREE COMPONENT COMPONENT COMPONENT PARENTCOMPONENTCOMPONENTCOMPONENT COMPONENT COMPONENT COMPONENT COMPONENTBA
  • 30.
    REACT TREE COMPONENT COMPONENT COMPONENT PARENTCOMPONENTCOMPONENTCOMPONENT COMPONENT C COMPONENT COMPONENTBA
  • 31.
    REACT TREE ROOT COMPONENT COMPONENT PARENTCOMPONENTCOMPONENTCOMPONENT COMPONENT C COMPONENT COMPONENTBA
  • 32.
    REACT TREE ROOT COMPONENT COMPONENT PARENTCOMPONENTCOMPONENTCOMPONENT COMPONENT C COMPONENT COMPONENTBA
  • 33.
    REACT TREE ROOT COMPONENT COMPONENT COMPONENTCOMPONENTCOMPONENTCOMPONENT COMPONENT C COMPONENT COMPONENTBA External Store?
  • 34.
    REACT TREE ROOT COMPONENT COMPONENT COMPONENTCOMPONENTCOMPONENTCOMPONENT COMPONENT C COMPONENT COMPONENTBA
  • 35.
    REACT TREE ROOT COMPONENT COMPONENT COMPONENTCOMPONENTCOMPONENTCOMPONENT COMPONENT C COMPONENT COMPONENTBA
  • 36.
    REACT TREE ROOT SHARED PARENT COMPONENT COMPONENTCOMPONENTCOMPONENT C COMPONENT COMPONENT COMPONENT COMPONENTBA
  • 37.
    REACT TREE ROOT SHARED PARENT COMPONENT COMPONENTCOMPONENT C COMPONENT COMPONENT D EBA SHARED PARENT 2
  • 38.
    const Color =React.createContext('black'); function ThemedCircle() { return ( <Color.Consumer> {color => <Circle color={color} />} </Color.Consumer> ) } <React.Fragment> <Color.Provider value="blue"> <ThemedCircle /><ThemedCircle /><ThemedCircle /> </Color.Provider> <Color.Provider value="red"> <ThemedCircle /><ThemedCircle /><ThemedCircle /> </Color.Provider> <ThemedCircle /><ThemedCircle /><ThemedCircle /> </React.Fragment>
  • 39.
    const Color =React.createContext('black'); function ThemedCircle() { return ( <Color.Consumer> {color => <Circle color={color} />} </Color.Consumer> ) } <React.Fragment> <Color.Provider value="blue"> <ThemedCircle /><ThemedCircle /><ThemedCircle /> </Color.Provider> <Color.Provider value="red"> <ThemedCircle /><ThemedCircle /><ThemedCircle /> </Color.Provider> <ThemedCircle /><ThemedCircle /><ThemedCircle /> </React.Fragment>
  • 40.
    const Color =React.createContext('black'); function ThemedCircle() { return ( <Color.Consumer> {color => <Circle color={color} />} </Color.Consumer> ) } <React.Fragment> <Color.Provider value="blue"> <ThemedCircle /><ThemedCircle /><ThemedCircle /> </Color.Provider> <Color.Provider value="red"> <ThemedCircle /><ThemedCircle /><ThemedCircle /> </Color.Provider> <ThemedCircle /><ThemedCircle /><ThemedCircle /> </React.Fragment>
  • 41.
    const Toggle =React.createContext({on: false, onToggle: () => {}}); class ToggleProvider extends React.Component { state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))}; render() { return ( <Toggle.Provider value={this.state}> {this.props.children} </Toggle.Provider> ); } } function ToggleButton() { return ( <Toggle.Consumer> {({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>} </Toggle.Consumer> ) } <ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider>
  • 42.
    const Toggle =React.createContext({on: false, onToggle: () => {}}); class ToggleProvider extends React.Component { state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))}; render() { return ( <Toggle.Provider value={this.state}> {this.props.children} </Toggle.Provider> ); } } function ToggleButton() { return ( <Toggle.Consumer> {({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>} </Toggle.Consumer> ) } <ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider>
  • 43.
    const Toggle =React.createContext({on: false, onToggle: () => {}}); class ToggleProvider extends React.Component { state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))}; render() { return ( <Toggle.Provider value={this.state}> {this.props.children} </Toggle.Provider> ); } } function ToggleButton() { return ( <Toggle.Consumer> {({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>} </Toggle.Consumer> ) } <ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider>
  • 44.
    const Toggle =React.createContext({on: false, onToggle: () => {}}); class ToggleProvider extends React.Component { state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))}; render() { return ( <Toggle.Provider value={this.state}> {this.props.children} </Toggle.Provider> ); } } function ToggleButton() { return ( <Toggle.Consumer> {({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>} </Toggle.Consumer> ) } <ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider> OFF OFF OFF
  • 45.
    const Toggle =React.createContext({on: false, onToggle: () => {}}); class ToggleProvider extends React.Component { state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))}; render() { return ( <Toggle.Provider value={this.state}> {this.props.children} </Toggle.Provider> ); } } function ToggleButton() { return ( <Toggle.Consumer> {({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>} </Toggle.Consumer> ) } <ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider> ON ON ON
  • 46.
    const Toggle =React.createContext({on: false, onToggle: () => {}}); class ToggleProvider extends React.Component { state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))}; render() { return ( <Toggle.Provider value={this.state}> {this.props.children} </Toggle.Provider> ); } } function ToggleButton() { return ( <Toggle.Consumer> {({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>} </Toggle.Consumer> ) } <ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider> OFF OFF OFF
  • 47.
    const Toggle =React.createContext({on: false, onToggle: () => {}}); class ToggleProvider extends React.Component { state = {on: false, onToggle: () => this.setState(s => ({on: !s.on}))}; render() { return ( <Toggle.Provider value={this.state}> {this.props.children} </Toggle.Provider> ); } } function ToggleButton() { return ( <Toggle.Consumer> {({on, onToggle}) => <button onClick={onToggle}>{on ? 'on' : 'off'} </button>} </Toggle.Consumer> ) } <ToggleProvider><ToggleButton /><ToggleButton /><ToggleButton /> </ToggleProvider> ON ON ON
  • 48.
    SUMMARY ▸ Functions beingfirst class values means we can use them as parameters to enable more flexible code re-use ▸ Using functions as parameters allows highly customisable shared components, complete with state and lifecycle hooks. ▸ React Context lets you share state across the tree of your application ▸ Context still uses the React tree. This means it works with server side rendering and you can safely use it in parts of your app, as well as using it as a whole app solution. @ForbesLindesay