Last active
April 12, 2018 07:54
-
-
Save michaelrambeau/8aea4945114b90053939191925768287 to your computer and use it in GitHub Desktop.
Advanced React Patterns V2 Workshop from https://github.com/kentcdodds/advanced-react-patterns-v2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compound Components | |
import React from 'react' | |
import {Switch} from '../switch' | |
class Toggle extends React.Component { | |
// you can create function components as static properties! | |
// for example: | |
// static Candy = (props) => <div>CANDY! {props.children}</div> | |
// Then that could be used like: <Toggle.Candy /> | |
// This is handy because it makes the relationship between the | |
// parent Toggle component and the child Candy component more explicit | |
// 🐨 You'll need to create three such components here: On, Off, and Button | |
// The button will be responsible for rendering the <Switch /> (with the right pros) | |
state = {on: false} | |
static On = ({on, children}) => on ? children : null | |
static Off = ({on, children}) => on ? null : children | |
static Button = ({on, toggle, ...props}) => <Switch on={on} onClick={toggle} {...props} /> | |
toggle = () => | |
this.setState( | |
({on}) => ({on: !on}), | |
() => this.props.onToggle(this.state.on), | |
) | |
render() { | |
// we're trying to let people render the components they want within the Toggle component. | |
// But the On, Off, and Button components will need access to the internal `on` state as | |
// well as the internal `toggle` function for them to work properly. So here we can | |
// take all this.props.children and make a copy of them that has those props. | |
// | |
// To do this, you can use: | |
// 1. React.Children.map: https://reactjs.org/docs/react-api.html#reactchildrenmap | |
// 2. React.cloneElement: https://reactjs.org/docs/react-api.html#cloneelement | |
// | |
// 🐨 you'll want to completely replace the code below with the above logic. | |
return React.Children.map(this.props.children, child => | |
React.cloneElement(child, { | |
on: this.state.on, | |
toggle: this.toggle, | |
}), | |
) | |
} | |
} | |
// Don't make changes to the Usage component. It's here to show you how your | |
// component is intended to be used and is used in the tests. | |
// You can make all the tests pass by updating the Toggle component. | |
function Usage({onToggle = (...args) => console.log('onToggle', ...args)}) { | |
return ( | |
<Toggle onToggle={onToggle}> | |
<Toggle.On>The button is on</Toggle.On> | |
<Toggle.Off>The button is off</Toggle.Off> | |
<Toggle.Button /> | |
</Toggle> | |
) | |
} | |
export {Toggle, Usage as default} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment