DEV Community

Cover image for Context vs Props in React
ryanAllMad
ryanAllMad

Posted on

Context vs Props in React

Hey! Thanks for dropping in. This article focuses on the difference between React props and React Context. I’ll walk you through a, hopefully, familiar concept to teach you how to use Context and when to use props.

Before we begin, go ahead and check out the code here. And see the app in action here.

Estimated reading time: 8 minutes

The Concept

If you’ve ever studied JavaScript and have touched on or dived into Objects, then you’re probably familiar with the Person example. To jog your memory, below is a Person object in Vanilla JS:

function Person(age, favoriteColor, hobbies, gender) {
this.age = age;
this.favoriteColor = favoriteColor;
this.hobbies = hobbies;
this.gender = gender;
}
Enter fullscreen mode Exit fullscreen mode

And if I wanted to create an object from this object (aka prototypal inheritance) then I’d do something like this:

const Mykol = new Person("30", "blue", "kicking ass, taking names", "female")
Enter fullscreen mode Exit fullscreen mode

Now that Mykol is a Person object, I can access information about her like this:

console.log(Mykol.age)
Enter fullscreen mode Exit fullscreen mode

Hopefully the above concept makes some sense to you. We’re going to use this same Person example to create a React app that uses both props and context to show the difference of these two concepts and when to use them.

For our project we’re going to use three friends and co-workers who all have individual qualities (as humans do) and one thing in common: they won’t go to the company retreat unless their friends are going.

Looking for more fun with Javascript concepts in React? Check out this Array Methods in React post here.

Getting Started

As always, we’re going to navigate to a project folder in our VS Code and open a terminal. Here we’ll use the Create React App command to spin up a React App:

npx create-react-app persons-context
Enter fullscreen mode Exit fullscreen mode

After that’s done:

  • remove all of the code inside the App.css file and save.
  • inside the App.js file, remove everything except the div with the className="App"
  • create a folder in the /src directory titled ‘components’
  • create a folder in the /src directory and title it ‘context’

Your App is now scaffolded and ready for us to begin working. If you want to add some text inside the App.js file inside the div with the className=”App” and run npm start in your terminal, you should. That can give you a good idea if you’ve scaffolded your project correctly or not.

Context

We’re going to start with our Context component. In this component we want to share the value that our Person’s components will share: Whether they are going to go to the company retreat or not.

  • Inside the /context folder create a file called PersonContext.js.
  • at the top of the file add: import { createContext, useState } from 'react'
  • on a new line add const PersonContext = createContext()
  • on a new line create the following function:
export const Provider = ({children}) => {
const [retreatStatus, setRetreatStatus] = useState('not going')

const data = {
        retreatStatus,
        changeRetreatStatus: () => {
            setRetreatStatus('going')
        }
    }

    return <PersonContext.Provider value={data}>{children}</PersonContext.Provider>
}
Enter fullscreen mode Exit fullscreen mode

Finally, at the bottom of the file, add your default export:

export default PersonContext
Enter fullscreen mode Exit fullscreen mode

Note that now you have a named export “Provider” and a default export “PersonContext”. Pay attention to the way we import these two exports to understand the difference between named exports and default exports.

How to Utilize Context

So that our app can utilize the Context we’ve just created, we need to navigate to our index.js file. At the top of this file, under your other import statements, import the named Provider export like so:

import { Provider } from './context/PersonContext'
Enter fullscreen mode Exit fullscreen mode

Inside the root.render function, we’re going to wrap our App component with the Provider component we’ve just imported.

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider>
      <App />
    </Provider>
  </React.StrictMode>
);
Enter fullscreen mode Exit fullscreen mode

That’s all we have to do to ensure that our components have access to the Context we’ve just created. But we still haven’t started using the context system yet. We’re going to move on to using props now and come back to how to access this Context in our components when it makes more sense to do so.

The Components

Inside of our /components folder, we’re going to create a Person component, an AriaLive component and three “People” components. Feel free to name these people whatever you want, I’m going to use my friends in this example.

Person Component

Starting with the Person component, in the /components folder create a file called Person.js

At the top of the file add your import statement like so:

import React, { useState, useEffect  } from "react"
Enter fullscreen mode Exit fullscreen mode

Note: notice that we are not using Context in this component, this is very important because this is a ‘parent’ component to our other components, yet there is no need to use Context here.

Next lets create our person. This component is going to use a lot of props, props that our child components are going to need. Under the import statements on a new line add the Person functional component:

const Person = ({ name, children, age, favoriteColor, hobbies, gender }) => {
    const [pronouns, setPronouns] = useState({subject: 'they', object: 'them'})
    const changePronouns = () => {
    if( gender === 'male') {
        setPronouns ({
            subject: 'he',
            object: 'him'
        })
    }
    if(gender ==='female') {
        setPronouns({
            subject: 'she',
            object: 'her'
        })
    }
   } 
   useEffect(() => changePronouns(), [])
    return (
    <div className={name}>
        <h3>{`${name.toUpperCase()}`}</h3>
        <h4>{age}</h4>
        <p>Gender: {`${gender}`}</p>
        <p>{`${name.toUpperCase()}`}'S favorite color is {`${favoriteColor}`}. {`${pronouns.subject.toUpperCase()}`} enjoys {`${hobbies}`}. 
        Today {`${pronouns.subject}`} is {children}
            to the company retreat. 
        </p>
    </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

This component probably looks very complicated and it does have some complexity. Let’s break it down. The component makes use of the following props:

  • name
  • children (not actual children, but React children)
  • age
  • favoriteColor
  • hobbies
  • gender

We are creating a piece of state for the pronouns. These pronouns are an object with 2 properties, the subject pronouns (such as he, she, they) and the object pronouns such as (him, her, them).

After that we are calling a function within the useEffect hook that will render the correct pronouns depending on the person’s gender.

Not too difficult when you break it down.

Context vs Props

Jason – A Person component

We’ll use Jason as our main example because he’s a great guy and we stan. Inside our components folder we’ll create a file called Jason.js

At the top of our file we’re going to import something new here, the useContext hook. And this will allow us to finally use the Context component we’ve created.

import React, { useContext } from "react"
import PersonContext from "../context/PersonContext"
import Person from "./Person"
Enter fullscreen mode Exit fullscreen mode

The Person Props

We’ll create our Jason functional component and assign the Person props some values. Notice how these values are individual values? I’ve left a comment where the children prop is being called. We’ll set that up next.

const Jason = () => {
    return  (
    <Person age="36" name="jason" favoriteColor="black" hobbies="writing, making stacks" gender="male">
        {/*something will go here*/}
    </Person>
    )

}

export default Jason
Enter fullscreen mode Exit fullscreen mode

Next its time to use the Context system finally. Below I’ve updated the Jason component. We are destructuring out the retreatStatus and changeRetreatStatus context from the PersonContext Provider. We are then creating a button component that will use these pieces of Context.

const Jason = () => {
    const { retreatStatus, changeRetreatStatus } = useContext(PersonContext)
    return  (
    <Person age="36" name="jason" favoriteColor="black" hobbies="writing, making stacks" gender="male">
        <button onClick={changeRetreatStatus}>{retreatStatus}</button>
    </Person>
    )

}

export default Jason
Enter fullscreen mode Exit fullscreen mode

Now in my App.js file I am going to import Jason into this file and return the Jason component within my App.

import React from "react"
import './App.css';
import Jason from './components/Jason';


function App() {
  return (
    <div className="App" role="main">
      <h1>Person Context App</h1>
      <h2>These are people. They all are individuals, but they have one thing in common, 
        they won't go to a retreat unless their friends are going too.</h2>
      <Jason />
    </div>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

I’ll repeat this process to make 2 more people. My App now looks like this below:

import React from "react"
import './App.css';
import Jason from './components/Jason';
import Mykol from './components/Mykol';
import Ryan from './components/Ryan';

function App() {
  return (
    <div className="App" role="main">
      <h1>Person Context App</h1>
      <h2>These are people. They all are individuals, but they have one thing in common, 
        they won't go to a retreat unless their friends are going too.</h2>
      <Jason />
      <Mykol />
      <Ryan />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

AriaLive – An accessibility feature

I like accessibility and aim to make everything I build be as accessible as possible. Therefore, so that this project would alert a non-visual user to changes in the document, I have created an AriaLive component within my /components folder. Below is the simple code for this component:

import React from "react"

const AriaLive = () => {

    return <span className="screen-reader-text" aria-live="polite">All of the friends are now going to the retreat</span>
}

export default AriaLive
Enter fullscreen mode Exit fullscreen mode

Here’s where it gets cool. Back in my App component I’m going to import this component and I want to conditionally render this aria-live region to my non-visual users when the retreatStatus changes to ‘going’. How I do this is by using Context once again.

I’ll first import useContext again and PersonContext. Then I’ll import the AriaLive component so that my import statements in my App.js file look like this once complete:

import React, { useContext } from "react"
import PersonContext from "./context/PersonContext"
import './App.css';
import Jason from './components/Jason'
import Mykol from './components/Mykol'
import Ryan from './components/Ryan'
import AriaLive from './components/AriaLive'
Enter fullscreen mode Exit fullscreen mode

Before my return statement I want to destructure the retreatStatus value from the PersonContext component. This is the only value I really need in my App component.

  const { retreatStatus } = useContext(PersonContext)
Enter fullscreen mode Exit fullscreen mode

Finally, within my App components return statement, I’m going to conditionally render this aria-live region like so:

  return (
    <div className="App" role="main">
      <h1>Person Context App</h1>
      <h2>These are people. They all are individuals, but they have one thing in common, 
        they won't go to a retreat unless their friends are going too.</h2>
      <Jason />
      <Mykol />
      <Ryan />
      {retreatStatus === 'going' && <AriaLive />}
    </div>
  );
Enter fullscreen mode Exit fullscreen mode

Want to learn more about what Aria actually is? Check out this WTH is WAI-ARIA post here.

Conclusion

This article focused on the difference between React props and React Context. Hopefully this project helped you to get familiar with these concepts and when to use each and why. Context is best to use when you want to pass values throughout your components but not necessarily from parent to child. Context is used well when the value is something your components share. Props are like individual traits, props get passed down from parent to child and are best used for defining individual properties. Hopefully the difference between Context and Props is a lot more clear to you. Thanks again for stopping by and for reading all the way to this part (impressive!).

Top comments (0)