Dev_felz
Dev_felz

Reputation: 11

Error of context consumer rendered with multiple children

Getting error of:

A context consumer was rendered with multiple children, or a child that isn't a function. A context consumer expects a single child that is a function. If you did pass a function, make sure there is no trailing or leading whitespace around it.

At first it was working but then the error started showing up. This is a vite + tailwindcss + react APP. I got error of cannot render context directly, so I added the Consumer code. But then this new error came up.

This is the context I created:

import React, {useState, createContext} from 'react'

// creating the food context
export const FoodContext = createContext()
export const FoodProvider = (props) => {

// state for the details
const [foods, setFoods] = useState([
{
            title: 'Dougnut',
            source: 'Delicious soft Dougnut',
            price: 500,
            imageUrl: "url('./images/pizza.jpg')",
            id: 1,
            buttonText: 'Order'
        },
        {
            title: 'Pasta',
            source:'Delicous pasta',
            price: 1500,
            imageUrl: '../images/banner.jpg',
            id: 6,
            buttonText: 'Order'
        }
    ]);

    return (
        <div>
            <FoodContext.Provider value={[foods, setFoods]}>
                {props.children}
            </FoodContext.Provider>
        </div>
    )
}

This is the main.js file where I wrapped all my contents with the context:

import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom';
import './index.css'
import App from './App'
import { FoodContext } from './components/context/FoodContext';

ReactDOM.render(
   <BrowserRouter>
      <FoodContext.Consumer>
          <App />
      </FoodContext.Consumer>
    </BrowserRouter>,
  document.getElementById('root')
)

And this is my app.js file:

import {Switch, Route } from 'react-router-dom';
import {FoodProvider} from "./components/context/FoodContext";
import HomePage from './components/HomePage';
import NotFound from './components/NotFound';
import Menu from './components/Menu';
import SingleFood from './components/SingleFood';

function App() {
  // const consumer = React.useContext(FoodProvider);
  return (
    <FoodProvider.Consumer>
      <div className="App">
        <Switch>
           <Route exact path='/' component={HomePage} />
           <Route path='/menu' component={Menu } />
           <Route path='/food/:id' component={SingleFood } />
           <Route path='*' component={NotFound } />
        </Switch>
      </div>
    </FoodProvider.Consumer>
  );
}

export default App;

Upvotes: 0

Views: 989

Answers (1)

Andrea Costanzo
Andrea Costanzo

Reputation: 2235

I think here there are different problems:

  1. I think you are using the consumer before declaring the provider. A context consumer must be a child (not direct) of the provider. To understand how context should be managed I suggest you gaining some knowledge about lifting state up first and then re-think your implementation.
  2. You can pass your state to the provider without putting the elements in a list. Using: <FoodContext.Provider value={{foods, setFoods}}> allows you to better destructure your context in children components.
  3. Your usage of the consumer doesn't also respect how you should use it. As you can see from the official documentation you should insert a single object based on the consumer value. So in your specific case, when you want to list your foods, you should have something like this:
 <FoodContext.Consumer>
  {
    ({ foods, setFoods }) => foods.map(food => (
      <div className="food-item">
        <h1>{food.title}</h1>
        {/*The remaining elements of your food component*/}
      </div>
    ))
  }
</FoodContext.Consumer>

Upvotes: 0

Related Questions