Skip to content

Commit ec3c3b2

Browse files
committed
flexible compound components
1 parent e0661a8 commit ec3c3b2

File tree

1 file changed

+25
-14
lines changed
  • epic-react-kent-c-dodds/04-Advanced-React-Patterns/src/exercise

1 file changed

+25
-14
lines changed

epic-react-kent-c-dodds/04-Advanced-React-Patterns/src/exercise/03.js

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,55 @@
44
import * as React from 'react'
55
import {Switch} from '../switch'
66

7-
// 🐨 create your ToggleContext context here
8-
// 📜 https://reactjs.org/docs/context.html#reactcreatecontext
7+
const ToggleContext = React.createContext(0)
98

109
function Toggle({children}) {
1110
const [on, setOn] = React.useState(false)
1211
const toggle = () => setOn(!on)
1312

14-
// 🐨 remove all this 💣 and instead return <ToggleContext.Provider> where
15-
// the value is an object that has `on` and `toggle` on it.
16-
return React.Children.map(children, child => {
17-
return typeof child.type === 'string'
18-
? child
19-
: React.cloneElement(child, {on, toggle})
20-
})
13+
const value = {on, toggle}
14+
15+
return (
16+
<ToggleContext.Provider value={value}>{children}</ToggleContext.Provider>
17+
)
18+
}
19+
20+
const useToggle = () => {
21+
const context = React.useContext(ToggleContext)
22+
if (!context) {
23+
throw new Error('useToggle must be used within a <Toggle/>')
24+
}
25+
return context
2126
}
2227

2328
// 🐨 we'll still get the children from props (as it's passed to us by the
2429
// developers using our component), but we'll get `on` implicitly from
2530
// ToggleContext now
2631
// 🦉 You can create a helper method to retrieve the context here. Thanks to that,
2732
// your context won't be exposed to the user
28-
// 💰 `const context = React.useContext(ToggleContext)`
33+
2934
// 📜 https://reactjs.org/docs/hooks-reference.html#usecontext
30-
function ToggleOn({on, children}) {
35+
36+
function ToggleOn({children}) {
37+
const {on} = useToggle()
3138
return on ? children : null
3239
}
3340

3441
// 🐨 do the same thing to this that you did to the ToggleOn component
35-
function ToggleOff({on, children}) {
42+
function ToggleOff({children}) {
43+
const {on} = useToggle()
3644
return on ? null : children
3745
}
3846

3947
// 🐨 get `on` and `toggle` from the ToggleContext with `useContext`
40-
function ToggleButton({on, toggle, ...props}) {
48+
function ToggleButton({...props}) {
49+
const {on, toggle} = useToggle()
4150
return <Switch on={on} onClick={toggle} {...props} />
4251
}
4352

44-
function App() {
53+
// const App = () => <ToggleButton />
54+
55+
const App = () => {
4556
return (
4657
<div>
4758
<Toggle>

0 commit comments

Comments
 (0)