DEV Community

Cover image for React TSX: passing props with useContext (beginner guide) Part 1/2
DennisVN
DennisVN

Posted on

React TSX: passing props with useContext (beginner guide) Part 1/2

I'm 7 months into coding now, simply love React so I dedicated to write my tech article about it. You can consider a 'classic' way of passing data, is passing data through a JSON list or Database. This often causes having to re-deconstruct the State in each new child component. To avoid this you can use the useContext hook in React, and pass it's props through a ContextProvider very easily.

This article will show you how to pass data from one central useContext that provides it's props to all components.
To go even further, we will edit the data and pass it to our screen and localStorage in part 2 of this beginner guide !
And yes, i mean ALL children. Let's start with context for now !

Action plan

In this example we are creating a restaurant's menu that displays a daily 3 course meal for Monday-Saturday. Before i spill the tea, let's start with the structure and action plan.

Please note that i expect you to have a basic understanding in React x TSX, and how components & React-Router-Dom works.
This however easily translates in JS for those who are not familiar in Typescript !

Let's get started !


In this project our initial Routing is structured as followed :

function App () {
<>
<div className="App>
    <Router>
    <Navbar>
    <Switch>
        <Route path="/menus" component={Menus}></Route>
    <Switch>
    <Navbar>
    <Router>
    <Footer>
</div>
</>
}
Enter fullscreen mode Exit fullscreen mode

Note that there are other components in the OG project, but these are irrelevant in our case.

Important before you proceed is making an action plan, by dedicating the correct Parent & Children. For our menu this will be as followed :

Component tree in App.tsx :


<Menus> = Parent Component 
-(redirected from App with Route to component={Menus}.)
    <MenuCard> = Child component 
-(This will be the "card" for the COMPLETE week. 
        <AddForm> = Child Component 
-( We need this later in a modal to edit the data )
Enter fullscreen mode Exit fullscreen mode

Where is your useContext i hear you think ? this is a global component so it has it's own place.

We will need a Provider to "inject" other components with it's props.
This means once you pass the props in a component, this comp will be "Provided" with the needed data !
Here we call it MenuContextProvider because obviously we are working on a Menu.

Step 1 : Setting up our useContext

First off, we obviously need to import & declare the context hook from React in this component :
-import { createContext } from "react";

Step 2 : Declaring data & objects inside context

To know how to pass the props we need to create our data and destructure it first.
We only need to do this once, here in this component.
Create a new State, which we will use as an Array of Objects.
Let's call this menus in our example ! This is how it looks :


const [menus, setMenus] = useState([
        { id: uuidv4(), day:"Monday", nameStarter: "Pôtage du jour", priceStarter: 4.20, nameMain: "Pomme d'amour", priceMain: 6.90 , nameDessert: "Salade du fruits", priceDessert: 4.20, totalPrice: 13.50, },
        { id: uuidv4(), day: "Tuesday", nameStarter: "Croquette crevette", priceStarter: 4.20 ,nameMain: "Moules Frites", priceMain: 6.90 , nameDessert: "Mousse au chocolat", priceDessert: 4.20, totalPrice: 13.50, },
        { id: uuidv4(), day: "Wednesday", nameStarter: "Croquette fromage", priceStarter: 4.20 , nameMain: "Pain Saucisse", priceMain: 6.90 , nameDessert: "Mousse au fraise", priceDessert: 4.20, totalPrice: 13.50, }, 
        { id: uuidv4(), day: "Thursday", nameStarter: "Croquette duo", priceStarter: 4.20 , nameMain: "Pain Fromage", priceMain: 6.90 , nameDessert: "Mousse au Camembert", priceDessert: 4.20, totalPrice: 13.50, },
        { id: uuidv4(), day: "Friday", nameStarter: "Cocktail of crevettes", priceStarter: 4.20 , nameMain: "Panette poison", priceMain: 6.90 , nameDessert: "Mousse au Brie", priceDessert: 4.20, totalPrice: 13.50, },
        { id: uuidv4(), day: "Saturday", nameStarter: "Carpaccio", priceStarter: 4.20 , nameMain: "Pain Jambon", priceMain: 6.90 , nameDessert: "Tiramisu", priceDessert: 4.20, totalPrice: 13.50, }
    ])
Enter fullscreen mode Exit fullscreen mode

There are some take aways here :

  • my French is lame
  • for id I used uuidv4(). You can go for a class with name Id, but often you will get an error as unique ID's are required for each item. uuidv4() creates random strings as an ID, which makes it easy to imply those unique ID's ! Don't forget to import this on top of our context component !
import { v4 as uuidv4 } from 'uuid';
Enter fullscreen mode Exit fullscreen mode

Step 3 : Setting up MenuContextProvider

We already know why we need a provider.
But how does it look, and how are we going to use and pass it ?

First off we need to create a new context. React does this with createContext. Again make sure you imported useContext on top of the component.

Since we are using typescript , we need to declare some extra types.

It took me a while to figure this out, but this is how it looks:

export const MenuContext = createContext< any | undefined>(undefined);

- const MenuContextProvider = (props) => {
    return(
        <MenuContext.Provider>
            {props.children}
        </MenuContext.Provider>
    )
}
export {MenuContextProvider}
Enter fullscreen mode Exit fullscreen mode

Note how we export the MenuContext as an Object aka {MenuContext} ! Important that we import this likewise in the other components.

Note how is different from !

  • < MenuContext.Provider > is only needed in our routing which needs the .Provider to send the props.
  • < MenuContextProvider > works as the function component and will be imported in other components to process the State.

Step 4 : Context & React-Router-DOM

This step will show you how to inject your routing and links with the props, and Provide the pages with the data.
In fact this is very easy; We place the .Provider around the Router. This means all components become a Child from the .Provider.
Crazy right ? This is how it looks in our App.tsx;

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Navbar from '../src/components/Navbar';
import Footer from './components/Footer';
import Menus from './components/Menus';
import {MenuContextProvider} from './contexts/MenuContext';

    function App () {
    <MenuContextProvider>
    <div className="App>
        <Router>
            <Navbar>
                <Switch>
                    <Route path="/menus" component={Menus}></Route>
                <Switch>
            <Navbar>
        <Router>
        <Footer>
    </div>
    </MenuContextProvider>
    }
    export default App;
Enter fullscreen mode Exit fullscreen mode

Don't forget to import the Provider on top of the component, and as mentioned, as an Object !
Well done, you injected the {props.children} of the context in all Child components !

Let sip our drink, and overview our MenuContextProvider component:

import { createContext, useEffect, useState } from "react";
import { v4 as uuidv4 } from 'uuid';

export const MenuContext = createContext< any | undefined>(undefined);

const MenuContextProvider = (props) => {

    const [menus, setMenus] = useState([
        { id: uuidv4(), day:"Monday", nameStarter: "Pôtage du jour", priceStarter: 4.20, nameMain: "Pomme d'amour", priceMain: 6.90 , nameDessert: "Salade du fruits", priceDessert: 4.20, totalPrice: 13.50, },
        { id: uuidv4(), day: "Tuesday", nameStarter: "Croquette crevette", priceStarter: 4.20 ,nameMain: "Moules Frites", priceMain: 6.90 , nameDessert: "Mousse au chocolat", priceDessert: 4.20, totalPrice: 13.50, },
        { id: uuidv4(), day: "Wednesday", nameStarter: "Croquette fromage", priceStarter: 4.20 , nameMain: "Pain Saucisse", priceMain: 6.90 , nameDessert: "Mousse au fraise", priceDessert: 4.20, totalPrice: 13.50, }, 
        { id: uuidv4(), day: "Thursday", nameStarter: "Croquette duo", priceStarter: 4.20 , nameMain: "Pain Fromage", priceMain: 6.90 , nameDessert: "Mousse au Camembert", priceDessert: 4.20, totalPrice: 13.50, },
        { id: uuidv4(), day: "Friday", nameStarter: "Cocktail of crevettes", priceStarter: 4.20 , nameMain: "Panette poison", priceMain: 6.90 , nameDessert: "Mousse au Brie", priceDessert: 4.20, totalPrice: 13.50, },
        { id: uuidv4(), day: "Saturday", nameStarter: "Carpaccio", priceStarter: 4.20 , nameMain: "Pain Jambon", priceMain: 6.90 , nameDessert: "Tiramisu", priceDessert: 4.20, totalPrice: 13.50, }
    ])


    return(
        <MenuContext.Provider value={{menus}}>
            {props.children}
        </MenuContext.Provider>
    )
}
export {MenuContextProvider};
Enter fullscreen mode Exit fullscreen mode

As you can see the value for the .Provider allready has the menus props passed.
This is the object that we created in our hook [menus, setMenus]. We don't use setMenus for now, so if you like you can remove it.

And there you go ! you just set up the useContext of an Array of Objecs, and dissected the props. From here you can easily deconstruct these props by passing them as a value for your components ! in part 2/2 i will show you how easy it is to get the wanted data, and also how to save them in localStorage. We go as far as creating a modal that pops up & where you can update the menu. Part one is allready quite the read, so i let you digest this one first ;) !

Thanks for peepin' & see you in part 2 !

Top comments (0)