React.js 04: Context API
Docs
lingo
"Components subscribing to state" ?
Context API
TLDR: app-wide states that you can inject anywhere
Context: How To
Contexts come with a .Provider
component that can also take in a value to be made available to child components – without having to prop drill the value.
Child components, acting as Consumers
, may subscribe to a Context’s value from their closest parent Provider
with React’s useContext()
hook.
Components subscribing to a Context
will receive the value for the Provider
closest to them in the application tree.
Providers
may be given an object containing the React state
and its corresponding state updater function. Subscribing child components may then use the state updater function to update the state for the Context.
Three parts:
Context providers
Context wrappers
useContext
Hook
Context: Example 1: Without Context API
// App.js
import React from "react";
import ReactDOM from "react-dom/client";
import { ContactItem } from "./ContactItem";
const family = [
{ name: "Finn the Human" },
{ name: "Jake the Dog" },
{ name: "Dan the Great" },
];
function App() {
return (
<>
<div>
<h1>Contact Item 1</h1>
<ContactItem name={family[0].name} theme="dark"/>
</div>
<div>
<h1>Contact Item 2</h1>
<ContactItem name={family[1].name} theme="light"/>
</div>
</>
);
}
export default App;
// ContactItem.js
import React from "react";
export const ContactItem = ({ name , theme }) => {
return (
<div className={`theme-${theme}`}>
{name} ! <br/><br/>
Prop theme is {theme} <br/>
</div>
);
};
Context: Example 1: With Context API
// ThemeContext.js
import React from 'react';
export const ThemeContext = React.createContext();
// App.js
import React from "react";
import ReactDOM from "react-dom/client";
import {ThemeContext} from "./ThemeContext";
import { ContactItem } from "./ContactItem";
const family = [
{ name: "Finn the Human" },
{ name: "Jake the Dog" },
{ name: "Dan the Great" },
];
function App() {
return (
<>
<ThemeContext.Provider value={"light"}>
<div>
<h1>Contact Item</h1>
<ContactItem name={family[0].name}/>
</div>
</ThemeContext.Provider>
<ThemeContext.Provider value={"dark"}>
<div>
<h1>Contact Item 2</h1>
<ContactItem name={family[1].name}/>
</div>
</ThemeContext.Provider>
</>
);
}
export default App;
// ContactsItem.js
import React , {useContext} from "react";
import {ThemeContext} from "./ThemeContext";
export const ContactItem = ({ name }) => {
const themeInContext = useContext(ThemeContext);
return (
<div className={`theme-${themeInContext}`}>
{name} ! <br/><br/>
Context theme is {themeInContext} {themeInContext === "dark" ? "🌑" : "☀"}
</div>
);
};
Context: Example 1: With Context API + Wrapper
// ThemeContext.js
import React , {useState} from 'react';
export const ThemeContext = React.createContext();
export const ThemeArea = ({children,initialTheme}) => {
const [count, setCount] = useState(0);
return (
<ThemeContext.Provider value={{initialTheme,count,setCount}}>
{children}
</ThemeContext.Provider>
);
};
// App.js
import React from "react";
import {ThemeArea} from "./ThemeContext";
import { ContactItem } from "./ContactItem";
const family = [
{ name: "Finn the Human" },
{ name: "Jake the Dog" },
{ name: "Dan the Great" },
];
function App() {
return (
<>
<ThemeArea initialTheme={"light"}>
<div>
<h1>Contact Item 1</h1>
<ContactItem name={family[0].name}/>
</div>
</ThemeArea>
<ThemeArea initialTheme={"dark"}>
<div>
<h1>Contact Item 2</h1>
<ContactItem name={family[1].name}/>
</div>
</ThemeArea>
</>
);
}
export default App;
// ContactItem.js
import React , {useContext} from "react";
import {ThemeContext} from "./ThemeContext";
export const ContactItem = ({ name }) => {
const { initialTheme, count, setCount } = useContext(ThemeContext);
return (
<div className={`theme-${initialTheme}`}>
{name} ! <br/><br/>
Context theme is {initialTheme} {initialTheme === "dark" ? "🌑" : "☀"} <br/><br/>
<button onClick={() => setCount(count => count+1)}>
Clicked: {count} time(s)
</button>
</div>
);
};
Context: Example 1: With Context API + Wrapper + 2 Buttons
ThemeContext.js
import React , {useState} from 'react';
export const ThemeContext = React.createContext();
export const ThemeArea = ({children,initialTheme}) => {
const [count, setCount] = useState(0);
const [fontSize, toggleFontSize] = useState("large");
return (
<ThemeContext.Provider value={{initialTheme,count,setCount,fontSize,toggleFontSize}}>
{children}
</ThemeContext.Provider>
);
};
App.js
import React from "react";
import {ThemeArea} from "./ThemeContext";
import { ContactItem } from "./ContactItem";
const family = [
{ name: "Finn the Human" },
{ name: "Jake the Dog" },
{ name: "Dan the Great" },
];
function App() {
return (
<>
<ThemeArea initialTheme={"light"}>
<div>
<h1>Contact Item 1</h1>
<ContactItem name={family[0].name}/>
</div>
</ThemeArea>
<ThemeArea initialTheme={"dark"}>
<div>
<h1>Contact Item 2</h1>
<ContactItem name={family[1].name}/>
</div>
</ThemeArea>
</>
);
}
export default App;
ContactItem.js
import React , {useContext} from "react";
import {ThemeContext} from "./ThemeContext";
export const ContactItem = ({ name }) => {
const { initialTheme, count, setCount, fontSize, toggleFontSize } = useContext(ThemeContext);
return (
<div className={`theme-${initialTheme}`}>
{name} ! <br/><br/>
Context theme is {initialTheme} {initialTheme === "dark" ? "🌑" : "☀"} <br/><br/>
<button onClick={() => setCount(count => count+1)}>
Clicked: {count} time(s)
</button><br/><br/>
<button onClick={() => toggleFontSize(toggleFontSize => (fontSize==="large") ? "regular" : "large")}>
Click To Switch Font Size
</button>
now it's "{fontSize}"
</div>
);
};
Context: Example 3
App.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ContactsSection } from "./ContactsSection";
import { ThemeArea } from "./ThemeContext";
const family = [{name: "Finn the Human"},{name: "Jake the Dog"}];
const friends = [{name: "Marceline"},{name: "Princess Bubblegum"}];
function App() {
return (
<div>
<h1>Contacts</h1>
// JXL tag for the context
<ThemeArea initialTheme="light">
<ContactsSection contacts={family} name="Family" />
</ThemeArea>
<ThemeArea initialTheme="dark">
<ContactsSection contacts={friends} name="Friends" />
</ThemeArea>
</div>
);
}
ThemeContext.js
import React , { useState } from "react";
// to get the props
export const ThemeContext = React.createContext();
// defines JXL tag to pass the prop
export const ThemeArea = ({ children, initialTheme }) => {
const [theme,setTheme] = useState(initialTheme);
return (
<ThemeContext.Provider value={{theme:theme,setTheme:setTheme}}>
{children}
</ThemeContext.Provider>
)
}
ContactsSection.js
import React from "react";
import { ContactsList } from "./ContactsList";
import { ThemeContext } from "./ThemeContext";
export const ContactsSection = ({ contacts, name }) => {
const {theme} = useContext(ThemeContext); // get the props
return (
<div className={`theme-${theme}`}>
<h2>{name}</h2>
<ContactsList contacts={contacts} />
</div>
);
};
Last updated