Leonard Kioi Kinyanjui
Learn & Build

Learn & Build

How to Prevent Nesting of Components in React

Photo by David Clode on Unsplash

How to Prevent Nesting of Components in React

Leonard Kioi Kinyanjui's photo
Leonard Kioi Kinyanjui
·Apr 24, 2022·

2 min read

Subscribe to my newsletter and never miss my upcoming articles

When making an application/library in React it may be necessary to prevent the nesting of components. Let's use an example to help understand the problem and the solution. When creating a presentation library you might have some components like:

  • Deck -> Represents a deck of slides
  • Slide -> Represents a slide in a deck
  • Text -> Text in a slide

The consumer of the library might have a setup like:

<Deck>
  <Slide>
    <Text>What is React?</Text>
  </Slide>
  <Slide>
    <Text>Using React in Production</Text>
  </Slide>
</Deck>

It doesn't make a lot of sense to have nested slides so a setup like this should be invalid:

<Deck>
  <Slide>
    <Text>What is React?</Text>
    <Slide>
      <Text>What are hooks?</Text>
    </Slide>
  </Slide>
</Deck>

This is an invalid use of the Slide component but how do you enforce this? The answer: React Context You need to create a context for the Slide component with null as the default value:

const SlideContext = React.createContext(null);

Then, in the Slide component get the current value of SlideContext and raise an error if the context has a value:

if (useContext(SlideContext)) {
  throw Error('Slide components cannot be nested');
}

Provide a value for the context somewhere after the check above in the Slide component:

<SlideContext.Provider value={{useAnimations: true}}>
  ...
</SlideContext.Provider>

SlideContext will only have a value if it had been used previously in a parent slide since we provide a value after the check useContext(SlideContext). A nested Slide will throw an error with the message Slide components cannot be nested.

<Deck>
  <Slide>
    <Text>What is React?</Text>
    <Slide>
      <Text>What are hooks?</Text>
    </Slide>
  </Slide>
</Deck>

In the first Slide useContext(SlideContext) will return null since at this point SlideContext does not have a value provided. The value will be provided in the line:

<SlideContext.Provider value={{useAnimations: true}}>

In the nested Slide, the expression useContext(SlideContext) will return the value {useAnimations: true} which had been set in the parent Slide so the error in the next line will be thrown.

Full code:

const SlideContext = React.createContext(null);

if (useContext(SlideContext)) {
  throw Error('Slide components cannot be nested');
}

<SlideContext.Provider value={{useAnimations: true}}>
  ...
</SlideContext.Provider>
 
Share this