Skip to content

Commit c4a2d23

Browse files
committed
context custom hook and reducer
1 parent 670699e commit c4a2d23

1 file changed

Lines changed: 39 additions & 21 deletions

File tree

  • epic-react-kent-c-dodds/03-Advanced-React-Hooks/src/exercise

epic-react-kent-c-dodds/03-Advanced-React-Hooks/src/exercise/03.extra-2.js

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,35 @@ import {useAsync} from '../utils'
2323
// 🐨 return your context provider with the value assigned to what you get back from useReducer
2424
// 💰 value={[cache, dispatch]}
2525
// 💰 make sure you forward the props.children!
26-
27-
function pokemonCacheReducer(state, action) {
28-
switch (action.type) {
29-
case 'ADD_POKEMON': {
30-
return {...state, [action.pokemonName]: action.pokemonData}
31-
}
32-
default: {
33-
throw new Error(`Unhandled action type: ${action.type}`)
26+
const PokemonCacheContext = React.createContext()
27+
28+
function PokemonCacheProvider(props) {
29+
function pokemonCacheReducer(state, action) {
30+
switch (action.type) {
31+
case 'ADD_POKEMON': {
32+
return {...state, [action.pokemonName]: action.pokemonData}
33+
}
34+
default: {
35+
throw new Error(`Unhandled action type: ${action.type}`)
36+
}
3437
}
3538
}
39+
const [cache, dispatch] = React.useReducer(pokemonCacheReducer, {})
40+
const value = [cache, dispatch]
41+
return <PokemonCacheContext.Provider value={value} {...props} />
42+
}
43+
44+
function usePokemonCache() {
45+
const context = React.useContext(PokemonCacheContext)
46+
if (!context) {
47+
throw new Error('usePokemonCache must be used in a PokemonCacheProvider.')
48+
}
49+
return context
3650
}
3751

3852
function PokemonInfo({pokemonName}) {
3953
// 💣 remove the useReducer here (or move it up to your PokemonCacheProvider)
40-
const [cache, dispatch] = React.useReducer(pokemonCacheReducer, {})
54+
const [cache, dispatch] = usePokemonCache()
4155
// 🐨 get the cache and dispatch from useContext with PokemonCacheContext
4256

4357
const {data: pokemon, status, error, run, setData} = useAsync()
@@ -55,7 +69,7 @@ function PokemonInfo({pokemonName}) {
5569
}),
5670
)
5771
}
58-
}, [cache, pokemonName, run, setData])
72+
}, [cache, dispatch, pokemonName, run, setData])
5973

6074
if (status === 'idle') {
6175
return 'Submit a pokemon'
@@ -70,7 +84,9 @@ function PokemonInfo({pokemonName}) {
7084

7185
function PreviousPokemon({onSelect}) {
7286
// 🐨 get the cache from useContext with PokemonCacheContext
73-
const cache = {}
87+
88+
const [cache] = usePokemonCache()
89+
7490
return (
7591
<div>
7692
Previous Pokemon
@@ -94,17 +110,19 @@ function PokemonSection({onSelect, pokemonName}) {
94110
// 🐨 wrap this in the PokemonCacheProvider so the PreviousPokemon
95111
// and PokemonInfo components have access to that context.
96112
return (
97-
<div style={{display: 'flex'}}>
98-
<PreviousPokemon onSelect={onSelect} />
99-
<div className="pokemon-info" style={{marginLeft: 10}}>
100-
<PokemonErrorBoundary
101-
onReset={() => onSelect('')}
102-
resetKeys={[pokemonName]}
103-
>
104-
<PokemonInfo pokemonName={pokemonName} />
105-
</PokemonErrorBoundary>
113+
<PokemonCacheProvider>
114+
<div style={{display: 'flex'}}>
115+
<PreviousPokemon onSelect={onSelect} />
116+
<div className="pokemon-info" style={{marginLeft: 10}}>
117+
<PokemonErrorBoundary
118+
onReset={() => onSelect('')}
119+
resetKeys={[pokemonName]}
120+
>
121+
<PokemonInfo pokemonName={pokemonName} />
122+
</PokemonErrorBoundary>
123+
</div>
106124
</div>
107-
</div>
125+
</PokemonCacheProvider>
108126
)
109127
}
110128

0 commit comments

Comments
 (0)