React Context在消费者中没有显示价值

时间:2019-09-30 13:18:55

标签: reactjs react-context

我正试图将值从Context Provider传递给Consumer,但它什么也没显示。

我已经在StackOverflow上看到了很多关于React Context无法正常工作的问题,但是我还没有发现任何可以帮助我的问题。我在Provider内部使用了Consumer,我尝试将Provider包装在div中(它帮助了一个人,但对我没有帮助),不是ContextTypes,因为它是旧版文档,没有关于错误的import-export的错误,没有拼写检查的错误,没有控制台的错误关于情境或被动影响情境。我做了所有类似上下文教程视频的工作,以适应我的项目。

我需要通过的 data.js 中有一个'productTemplate':

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 中的Provider中:

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>

result

markup in DevTools

我知道,这可能是一个幼稚的错误,但这只是我在React上的第二个项目。请帮帮我。

1 个答案:

答案 0 :(得分:0)

问题是productTemplate是一个值数组(不是对象)。将来,在调试时,我建议从上下文记录整个value(而不是立即使用它)。例如,在return <StyledDivProductPage ...ProductPage的前面添加一个console.log(value)

这样做表明productTemplate是一个数组,因此访问productTemplate.title将是undefined(这就是为什么不呈现任何内容的原因)。

这可以通过访问第一项来解决:

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

或更新状态下的初始值,例如:

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