Youāre now going to learn to work with the member of the hooks family that lets you easily use React Context.
Whatās React Context? š¤
Context is a way of easily sharing props between components. Itās native to React, so there is no need to install anything else.
If you took the previous course, youād have seen how toĀ pass simple props between parent and child componentsĀ and how toĀ use props to lift state up. But can you imagine what that would be like in a complex application, where to pass a prop to a child component, youād have toĀ go through dozens of parent componentsĀ that donāt need it?Ā Ā

Enter React Context, which lets youĀ get your data without having to pass it manually. To do this, wrap the parent component that is highest up in the component tree with a Ā ProviderĀ . All child components will then be able to connect to the Ā ProviderĀ , thereby accessing the props without having to go through all of the components in between. These child components are known as Ā ConsumersĀ .

The notion of quickly passing data between components is at the heart of many issues, ensuring code performs well and is readable. In particular, there are many discussions on how to manage state in a comprehensible way that performs well. This is known asĀ state management. Ring any bells?
Before hooks came along, using context was much more difficult. Count yourself lucky that the Ā useContextĀ hook exists! šĀ
useContextNow that you know what context is, letās put it to work in the Shiny application.
What data should we put in the context?
Reactās documentation states that āContext is designed to share data that can be considered global,ā for example, current authenticated user, theme, or preferred language.Ā
Letās start byĀ creating a dark mode for the app. As youāll know, this is a theme using darker colors that gives your eyes a rest when looking at the screen.Ā
To set this up, create a footer in whichĀ you add a button. InĀ Ā /componentsĀ , create aĀ Ā Footer/index.jsxĀ file that works in quite a basic way:
import styled from 'styled-components'
import colors from '../../utils/style/colors'
const FooterContainer = styled.footer`
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding-top: 60px;
`
const NightModeButton = styled.button`
background-color: transparent;
border: none;
cursor: pointer;
color: ${colors.secondary};
`
function Footer() {
return (
<FooterContainer>
<NightModeButton>Switch mode</NightModeButton>
</FooterContainer>
)
}
export default FooterUse this button in the footer to switch to dark mode in the app. Now create the context provider for the theme. To do this, make a folder especially for context in Ā utils/contextĀ . Then create an Ā index.jsx fileĀ .
To start, import Ā { createContext }Ā from Ā reactĀ , and set upĀ theĀ context for the theme with:
export const ThemeContext = createContext()Next use Ā ThemeContextĀ :
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light')
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light')
}
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
)
}Weāve created a component that wrapsĀ the parent component with the theme Ā ProviderĀ . The Ā themeĀ state and the function to modify it, Ā setThemeĀ , are passed in the Ā valuesĀ . This means that all the child components wrapped by the Ā ProviderĀ will be able to access Ā themeĀ and Ā setThemeĀ .
Itās now time to useĀ theĀ ProviderĀ at the highest level whereĀ components will need access to the context. Put it in Ā index.jsxĀ at the Ā /src rootĀ . That gives you:
ReactDOM.render(
<React.StrictMode>
<Router>
<ThemeProvider>
<GlobalStyle />
<Header />
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/survey/:questionNumber">
<Survey />
</Route>
<Route path="/results">
<Results />
</Route>
<Route path="/freelancers">
Freelancers />
</Route>
<Route>
<Error />
</Route>
</Switch>
<Footer />
</ThemeProvider>
</Router>
</React.StrictMode>,
document.getElementById('root')
)Does this mean that we have to put theĀ Ā ProviderĀ at the level ofĀ the Ā routerĀ ? š¤
Well, not necessarily! As its name suggests, context ācontextualizesā your data. Certain parts of the application need to know about certain parts of state, while others donāt. Itās up to you to decide where best to put it.
useContextBut wait, whatās Ā useContextĀ ?
useContextĀ is a hook used for āhookingā from a child component that has been wrapped by a Ā ProviderĀ , providing easy access to the shared state.Ā
Letās give it a go.
First, use the Ā themeĀ to make a very visible modification: changing the Ā background-colorĀ across the whole application.
Before,Ā GlobalStyleĀ was in theĀ index.jsxĀ file at the Ā /srcĀ root, but now move it into a separate file in Ā /utils/style/GlobalStyle.jsxĀ . Youāre also going to changeĀ Ā GlobalStyleĀ to a function componentĀ that allows you to use hooks (before, it was just a styled-component). That gives you:
function GlobalStyle() {
return <StyledGlobalStyle />
}Next, import Ā ThemeContextĀ and Ā useContextĀ with:
import { useContext } from 'react'
import { ThemeContext } from '../context/ThemeProvider'Which lets youĀ get the theme:
function GlobalStyle() {
const { theme } = useContext(ThemeContext)
return <StyledGlobalStyle isDarkMode={theme === 'dark'} />
}Pass an isDarkModepropĀ according to the theme activated.Ā
InĀ StyleĀ , use it like this:
const StyledGlobalStyle = createGlobalStyle`
* {
font-family: 'Trebuchet MS', Helvetica, sans-serif;
}
body {
/* Here this syntax goes back to the same as
background-color: ${({ props }) =>
props.isDarkMode ? '#2F2E41' : 'white'};
*/
background-color: ${({ isDarkMode }) => (isDarkMode ? 'black' : 'white')};
margin: 0;
}
`Ā All that remains now is to tackle the final piece ofĀ the puzzle: implementing the button changes modes. āļø/š
So letās go back toĀ Footer/index.jsxĀ . Just like earlier, importĀ Ā ThemeContextĀ and Ā useContextĀ .
Then get theĀ action Ā toggleThemeĀ and Ā themeĀ with:
const { toggleTheme, theme } = useContext(ThemeContext)You can use it just underneath:
function Footer() {
const { toggleTheme, theme } = useContext(ThemeContext)
return (
<FooterContainer>
<NightModeButton onClick={() => toggleTheme()}>
Switch mode : {theme === 'light' ? 'āļø' : 'š'}
</NightModeButton>
</FooterContainer>
)
}Letās test it out.
Amazing! š¤©

Great work: youāve just created a context and used it with Ā useContextĀ to create a dark mode in your application. š
As Iāve said, youāre lucky. Before hooks came along, context was much harder to implement. Watch the demonstration below to see how it used to work. š
Itās time to put all of this into practice. For this exercise, youāll use context to get the results of your survey between pages.
Start the exercise on branchĀ P2C2-begin. In Ā context/index.jsxĀ , youāll find a ready-to-use Ā SurveyProviderĀ .
InĀ Ā /Survey/index.jsxĀ , youāll find the codebase for storing user responses in the context and buttons for entering responses.
Like in the first course, youāre using the spread operator to storeĀ the object. Remember learning that state is immutable in the chapter āShare State Between Different Componentsā? For this exercise, do the following:
Use Ā useThemeĀ in your Ā Footer/index.jsxĀ .
Use your Ā SurveyProviderĀ in Ā src/index.jsxĀ .
Save the results in your state from Ā pages/Survey/index.jsxĀ .
Get the results in Ā /pages/results.jsxĀ with Ā useContextĀ , and display them in a simple Ā console.log()Ā .
If you struggle, youāll find all of the code for the solution on branchĀ P2C2-solution.
Context is a React feature for sharing state between several parent and child components with the help of a provider.Ā
useContextĀ Ā is a hook that lets you easily āhook intoā context, thereby accessing shared state.
Using context is one method of state management, which can be combined with other methods such as Redux.Ā
So, how was using context in your application with the useContext hook?
In the next chapter, youāll learn more about hooks by creating your own custom ones. Youāll even see how to create your own useFetchĀ hook to call an API. Sounds like fun, doesnāt it? š