Last active
January 22, 2021 21:54
-
-
Save brentsowers1/e4793670a845ec22af265339f27e7ed5 to your computer and use it in GitHub Desktop.
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
import React, { useState, useContext, createContext } from 'react'; | |
// We have to define a context object for each unique piece of shared state. | |
// Parameter is the default value - in our case we're making it an object | |
// with a value, and a function to set that value. The Provider will | |
// populate the function | |
const CounterContext = createContext({ | |
value: 0, | |
setValue: () => {}, | |
}); | |
// This will be a high level component in our application that can read from | |
// context. We'll sneak in a function to update the value inside of the | |
// context object so we can easily update it in children. | |
const CounterProvider = ({ children }) => { | |
const counterInitialState = { | |
value: 0, | |
setValue: newValue => { | |
// The actual context is an object with the value and function to update | |
// it (what we're defining now), but we only want to update the value | |
// itself. So we have to follow the reducer format (ugh) to return a new | |
// object with a new value for counterValue, but preserve the other keys | |
// in the object (this function) | |
// eslint-disable-next-line no-use-before-define | |
setCounterState(prevState => { | |
return { | |
...prevState, | |
value: newValue, | |
}; | |
}); | |
}, | |
}; | |
const [counterState, setCounterState] = useState(counterInitialState); | |
return ( | |
<CounterContext.Provider value={counterState}> | |
{children} | |
</CounterContext.Provider> | |
); | |
}; | |
const ContextExample = () => { | |
return ( | |
<div> | |
<CounterProvider> | |
Main app container | |
<CounterDisplay /> | |
<CounterIncrementer /> | |
</CounterProvider> | |
</div> | |
); | |
}; | |
const CounterIncrementer = () => { | |
// useContext will return the current version of what gets set as the value | |
// in the Provider. It's an object with two properties. You'll get a new | |
// value in here whenever it changes, it's very much like useState! In fact | |
// you could write this line as: | |
// const { value, setValue } = useContext(CounterContext) | |
const counter = useContext(CounterContext); | |
return ( | |
<div> | |
{/* eslint-disable-next-line jsx-a11y/control-has-associated-label,react/button-has-type */} | |
Increment - <button onClick={() => counter.setValue(counter.value + 1)} /> | |
</div> | |
); | |
}; | |
const CounterDisplay = () => { | |
const counter = useContext(CounterContext); | |
return <div>Counter value = {counter.value}</div>; | |
}; | |
export default ContextExample; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment