反应引用其他状态属性的JS状态

时间:2018-08-08 05:38:45

标签: reactjs typescript

我想拥有一个包含产品列表和listItems列表的组件,该组件可呈现每个产品,但这给了我错误:

TypeError: Cannot read property 'products' of undefined
new ProductList
src/components/products/ProductList.js:11

这是我的代码:

import React, { Component } from "react";
import productData from "./model";
import Product from "./Product"

class ProductList extends Component {

  constructor(props) {
    super(props);
    this.state = {
      products: productData,
      listItems: this.state.products.map(product => (
        <Product key={product.name.toString()} product={product} />
      ))
    };
  }

  addProduct = (product) => {
    this.state.products.push(product);
    this.setState({
      products: this.state.products
    });
  };

  render() {
    return (
        <div>
        <ul>{this.state.listItems}</ul>
        <button onClick={e => this.addProduct({name: "some product", price: 54})}>Add Product</button>
      </div>
    );
  }
}

export default ProductList;

model.js:

interface Product {
  name: string;
  price: number;
}

let productData: Array<Product> = [
  { name: "Sledgehammer", price: 125.75 },
  { name: "Axe", price: 190.5 },
  { name: "Bandsaw", price: 562.13 },
  { name: "Chisel", price: 12.9 },
  { name: "Hacksaw", price: 18.45 }
];

export default productData

当我更改为:

  listItems: this.products.map(product => (
    <Product key={product.name.toString()} product={product} />
  ))

我得到:

TypeError: Cannot read property 'map' of undefined

我在做什么错了?

2 个答案:

答案 0 :(得分:1)

我认为您要在初始化状态时映射productsData而不是this.state

listItems: productsData.map(product => (
  <Product key={product.name.toString()} product={product} />
))

您可能可以将listItem从状态中移出,只需在render方法中重新创建

render() {
  const listItems = this.state.products.map(product => (
    <Product key={product.name.toString()} product={product} />
  ))

  return (
    <div>
      <ul>{listItems}</ul>
      <button onClick={e => this.addProduct({name: "some product", price: 54})}>Add Product</button>
    </div>
  );
}

或在addProduct方法中重新计算listItems状态-

addProduct = (product) => {
  const newProducts = this.state.products.concat(product)
  this.setState({
    products: newProducts,
    listItems: newProducts.map(product => (
      <Product key={product.name.toString()} product={product} />
    ))
  });
};

答案 1 :(得分:0)

在第一段代码中,您具有:

this.state = {
  products: productData,
  listItems: this.state.products.map(product => (
    <Product key={product.name.toString()} product={product} />
  ))
};

此时,this.stateundefined,并且正在分配值。后续的自引用调用this.state.products试图在this.state上找到产品属性undefined

在第二段代码中,您具有:

this.state = {
  products: productData,
  listItems: this.products.map(product => (
    <Product key={product.name.toString()} product={product} />
  ))
};

对于this.products,是对实例ProductList上的products属性的引用,该实例也不存在。

尝试这样的事情:

import React, { Component } from "react";
import productData from "./model";
import Product from "./Product";

class ProductList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      products: productData
    };
  }

  addProduct = product => {
    const { products } = this.state;

    this.setState({
      products: [...products, product]
    });
  };

  render() {
    const { products } = this.state;

    return (
      <div>
        <ul>
          {products.map(product => (
            <Product key={product.name.toString()} product={product} />
          ))}
        </ul>
        <button
          onClick={e => this.addProduct({ name: "some product", price: 54 })}
        >
          Add Product
        </button>
      </div>
    );
  }
}

export default ProductList;

作为一般的经验法则,状态应包含视图的数据模型。我们生成的html,例如<Product />,应该是状态和道具的结果,并且应该存在于render函数中。