Skip to content

Instantly share code, notes, and snippets.

@kentcdodds
Last active September 18, 2018 23:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kentcdodds/1f1de76e325f1d0a4689f5de53fb0e59 to your computer and use it in GitHub Desktop.
Save kentcdodds/1f1de76e325f1d0a4689f5de53fb0e59 to your computer and use it in GitHub Desktop.
A Render Prop by Any Other Name: React
const {Provider, Consumer: ThemeConsumer} = React.createContext()
class ThemeProvider extends React.Component {
setTheme = theme => this.setState({theme})
state = {theme: 'dark', setTheme: this.setTheme}
render() {
return <Provider value={this.state} {...this.props} />
}
}
function AccordionButton({isOpen, ...props}) {
return (
<ThemeConsumer>
{({theme}) => (
<button
className={`accordion accordion-${theme} ${isOpen ? 'open' : 'closed'}`}
{...props}
/>
)}
</ThemeConsumer>
)
}
<ThemeProvider>
...
...
<AccordionButton
{...getButtonProps({isOpen: openIndexes.includes(index)})}
>
{`${item.title} ${openIndexes.includes(index) ? '👇' : '👈'}`}
</AccordionButton>
...
...
</ThemeProvider>
<Accordion>
{({openIndexes, getButtonProps}) => (
<div>
{items.map((item, index) => (
<AccordionItem key={item.title}>
<AccordionButton
{...getButtonProps({isOpen: openIndexes.includes(index)})}
>
{`${item.title} ${openIndexes.includes(index) ? '👇' : '👈'}`}
</AccordionButton>
<AccordionContents isOpen={openIndexes.includes(index)}>
{item.contents}
</AccordionContents>
</AccordionItem>
))}
</div>
)}
</Accordion>
import {
preventClose, // prevents the state from having all open indexes closed
single, // allows only one open index at a time
combineReducers, // accepts any number of reducers and calls each of them in turn
} from './reducers';
// composes the Accordion into a component that uses the logic for a Tabs UI
const Tabs = ({stateReducer = (state, changes) => changes, ...props}) => (
<Accordion
stateReducer={combineReducers(single, preventClose, stateReducer)}
{...props}
/>
)
// usage:
<Tabs>
{({openIndexes, getButtonProps}) => (
<div>
<TabButtons>
...
</TabButtons>
<TabItems>
...
</TabItems>
</div>
)}
</Tabs>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment