Контекст реагирования не показывает значение в Consumer - PullRequest
0 голосов
/ 30 сентября 2019

Я пытаюсь передать значение от провайдера контекста потребителю, но он ничего не показывает.

Я наблюдал много вопросов на StackOverflow о неработающем React Context, но я не нашел ничего, что могло быПомоги мне. Я использую Consumer внутри Provider, я пытался обернуть Provider в div (это помогло кому-то, но не мне), ContextTypes не так, так как это устаревший документ, нет ошибок в неправильном импорте-экспорте, нет ошибок проверки правописания, нет ошибок консолиотносительно контекста или пассивно влияющего на контекст. Я сделал все как в видео-уроке по контексту, адаптируясь к моему проекту.

У меня есть «productTemplate» в data.js , который мне нужно передать:

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
  }
];

У меня есть отдельный файл для контекста - 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>

Все приложение упаковано в провайдера в 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>

В ProductPage.js Я тестирую контекст свойства 'title', но он ничего не показывает:

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>

результат

разметка в DevTools

Я так понимаю, этовозможно, это детская ошибка, но это всего лишь мой второй проект на React. Пожалуйста, помогите мне.

1 Ответ

0 голосов
/ 30 сентября 2019

Проблема в том, что productTemplate - это массив значений (не объект). В будущем при отладке я бы порекомендовал регистрировать весь value из контекста (а не использовать его сразу). Например, прямо перед return <StyledDivProductPage ... в ProductPage добавьте console.log(value).

. Это покажет, что productTemplate - это массив, поэтому доступ к productTemplate.title будет undefined (поэтому ничего не происходит. rendered).

Это можно исправить, обратившись к первому элементу:

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

или обновив начальное значение в состоянии, например:

const productTemplate = { ... } // instead of [{ ... }]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...