Skip to content

TodayILearned - 2023-07-28

Posted on:July 28, 2023 at 07:58 AM

Today’s TIL is on React’s use of Context. Please note, all the code I have provided below, unless explicitly stated otherwise, is from React.dev docs.

Context: why?

Use case

Maybe you have a

Component and within it, you want its directly descending children of Components to have the same size. With props, you would have to pass a prop to each and every < Heading />

// App.jsx 
<Section>
  <Heading level={3}>About</Heading>
  <Heading level={3}>Photos</Heading>
  <Heading level={3}>Videos</Heading>
</Section>

This is kind of cumbersome - can we somehow pass {3} to the Section and have the Heading components access it without receiving it as a prop? Answer: CONTEXT!

Syntax for creating context:

// LevelContext.jsx
import { createContext } from 'react'; 

export const LevelContext = createContext(1);  // 1 is the default value 

You usually create the context as a separate module/file. Then, if you want to utilize this specific context in your JSX files:

// Heading.jsx
import { useContext } from 'react'; 
import { LevelContext } from './LevelContext.js';

With these two import statements, you import the useContext hook from react, and also import the context you want to utilize.

For the component that needs to receive this data, you utilize the useContext hook:

// Heading.jsx
import { useContext } from 'react'; 
import { LevelContext } from './LevelContext.js';

export const Heading = () => {
   const level = useContext(LevelContext);
   //
}

Since the Heading doesn’t directly receive the level prop, you now set that value on

. To accurately provide the LevelContext, Section.jsx needs to have the following code:

import { LevelContext } from './LevelContext.js';

export default function Section({ level, children }) {
  return (
    <section className="section">
      <LevelContext.Provider value={level}>
        {children}
      </LevelContext.Provider>
    </section>
  );
}

Note, you use a method of LevelContext, Provider() and set a value of the heading level you’d like. Also, LevelContext.Provider() doesn’t necessarily have to be in the immediate parent component (Section.jsx) in this case, depending on what you’re trying to achieve.

Caution: Don’t overuse context

React.dev’s recommendation prior to using Context:

  1. Pass the information as props
  2. Extract components and pass JSX as children to them.

More on the second method:

  • For example, let’s say you have <App /> -> <Layout /> -> and <Post/> components and want to pass postList state from App to Post. You will have to pass postList from App to Layout, and then Post. Technically, since the Layout component doesn’t need the postList prop, instead of writing <Layout postList={postList} />, you can have Layout take children as a prop, and write <Layout><Posts postList={postList} /></Layout>.