By Noir


2019-09-30 13:18:55 8 Comments

I'm trying to pass value from Context Provider to Consumer, but it shows nothing.

I've watched many questions on StackOverflow about React Context not working, but I haven't found anything that could help me. I use Consumer inside Provider, I tried to wrap Provider in div (it helped someone, but not me), ContextTypes are not the case, since it's a legacy doc, no mistakes about wrong import-export, no spellchecking mistakes, no console mistakes regarding context or passively affecting context. I did everything like in context tutorial video, adapting to my project.

I have a 'productTemplate' in data.js that I need to pass:

export const productTemplate = [
  {
    id: 1,
    title: "Samsung Galaxy S10",
    company: "Samsung",
    description: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Laudantium harum ipsam maiores excepturi, enim quae ex consectetur magnam quo temporibus error, vel iure eveniet id quas expedita cum cupiditate autem!",
    imageSrc: "samsung-galaxy-s10-1.webp",
    imageWidth: 200,
    imageHeight: 200,
    price: 300,
    isInCart: false,
    amountInCart: 0
  }
];

I have separate file for context - context.js:

import React, { Component } from 'react';
import { products, productTemplate } from './data'; // <-- imported 'productTemplate' correctly

const Context = React.createContext();

class ContextProvider extends Component {
  constructor() {
    super();
    this.state = {
      products: [],
      productTemplate: productTemplate  // <-- I need to pass it
    };

    this.setProducts = this.setProducts.bind(this);
    this.getItem = this.getItem.bind(this);
    this.onDetail = this.onDetail.bind(this);
  }

  // Don't mind next 4 methods, they're not related to 'productTemplate'

  componentDidMount() {
    this.setProducts();
  }

  setProducts() {
    let tempProducts = JSON.parse(JSON.stringify(products));
    this.setState(() => {
      return {products: tempProducts}
    })
  }

  getItem(id) {
    const product = this.state.products.find(item => item.id === id);
    return product;
  }

  onDetail(id) {
    const product = this.getItem();
    this.setState(() => {
      return { detailProduct: product }
    });
  }

  render() {
    return (
      <Context.Provider value={{ 
        ...this.state,                 // <-- passed this.state in value
        setProducts: this.setProducts,
        getItem: this.getItem,
        onDetail: this.onDetail
      }}>
        {this.props.children}
      </Context.Provider>
    )
  }
}

const ContextConsumer = Context.Consumer;

export { ContextProvider, ContextConsumer };
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

The whole App is wrapped in Provider in index.js:

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

ReactDOM.render(
  <ContextProvider>
    <Router>
      <App />
    </Router>
  </ContextProvider>, 
  document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

In ProductPage.js I'm testing context on 'title' property, but it shows nothing:

import React, { Component } from 'react';
import { StyledDivProductPage, StyledNavBreadcrumbs } from '../styles';
import { Link } from "react-router-dom";
import {  ContextConsumer } from '../context';

export default class ProductPage extends Component {
  render() {
    return (
      <ContextConsumer>
        {value => {
          const { id, title, company, description, imageSrc, price, isInCart, amountInCart } = value.productTemplate;
        
          return (
            <StyledDivProductPage>
              <StyledNavBreadcrumbs aria-label="breadcrumb" className="align-self-start">
                <ol className="breadcrumb">
                  <li className="breadcrumb-item"><Link to="/">Home</Link></li>
                  <li className="breadcrumb-item"><Link to="/mobile_phones">Mobile Phones</Link></li>
                  <li className="breadcrumb-item active" aria-current="page">{title}</li> {/*<-- here should be title value, but it shows nothing */}
                </ol>
              </StyledNavBreadcrumbs>
            </StyledDivProductPage>
          )
        }}
      </ContextConsumer>
    )
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

result

markup in DevTools

I understand, it may be a childish mistake, but it's only my second project on React. Please, help me.

1 comments

@skovy 2019-09-30 13:31:15

The problem is productTemplate is an array of values (not an object). In the future, when debugging, I would recommend logging the entire value from context (rather than using it right away). For example, right before return <StyledDivProductPage ... in ProductPage add a console.log(value).

Doing so shows that productTemplate is an array so accessing productTemplate.title will be undefined (which is why nothing is rendered).

This can be fixed by accessing the first item:

const { id, title, ... } = value.productTemplate[0]; // access the first element

Or update the initial value in state, for example:

const productTemplate = { ... } // instead of [{ ... }]

Related Questions

Sponsored Content

37 Answered Questions

[SOLVED] What is the difference between React Native and React?

64 Answered Questions

[SOLVED] Loop inside React JSX

  • 2014-04-05 05:29:28
  • Ben Roberts
  • 842797 View
  • 1301 Score
  • 64 Answer
  • Tags:   javascript reactjs

32 Answered Questions

[SOLVED] React js onClick can't pass value to method

  • 2015-04-22 23:40:14
  • user1924375
  • 537649 View
  • 646 Score
  • 32 Answer
  • Tags:   javascript reactjs

33 Answered Questions

[SOLVED] Programmatically navigate using react router

  • 2015-06-26 17:38:51
  • George Mauer
  • 758305 View
  • 1474 Score
  • 33 Answer
  • Tags:   reactjs react-router

26 Answered Questions

[SOLVED] What do these three dots in React do?

  • 2015-06-25 11:21:52
  • Thomas Johansen
  • 278232 View
  • 922 Score
  • 26 Answer
  • Tags:   javascript reactjs

29 Answered Questions

[SOLVED] Show or hide element in React

  • 2014-07-01 05:17:00
  • user1725382
  • 653760 View
  • 546 Score
  • 29 Answer
  • Tags:   javascript reactjs

5 Answered Questions

1 Answered Questions

How to fix this error when using React Context

1 Answered Questions

1 Answered Questions

[SOLVED] How get value datapicker in react toobox custom?

  • 2017-06-05 18:14:51
  • Luiz Carlos Pedroso Gomes
  • 1562 View
  • 3 Score
  • 1 Answer
  • Tags:   reactjs react-toolbox

Sponsored Content