我有一个React应用,可从Json文件中获取“产品”详细信息。它们显示正确,并且“递增-递减”按钮可以正常工作。
因此在index.js中,三个js组件分别称为main.js,header.js和footer.js。
Main获取json文件,然后创建容器并行,然后调用8次(因为Json中存在8个项目)product.js,在Product.js中,有关产品和单个按钮的所有信息都显示在页面上。
这是我的问题: 使每个物料数量乘以相关价格并在标题中添加总数量和总价格的最简单方法是什么?
索引
import React from "react";
import ReactDOM from "react-dom";
import Main from "./components/main";
import Footer from "./components/footer";
import Header from "./components/header";
import './index.css';
import 'bootstrap/dist/css/bootstrap.css';
ReactDOM.render(<Main />, document.getElementById("root"));
ReactDOM.render(<Header />, document.getElementById("header"));
ReactDOM.render(<Footer />, document.getElementById("footer"));
标题
import React, { Component } from "react";
class header extends Component {
state = {
totalPrice: 200,
totalQuantity:0
};
render() {
return (
<div>
<nav className="navbar navbar-expand-lg navbar-dark bg-info">
<a className="navbar-brand" href="#">
<img src="./logo.png" id="logo" alt="" />
</a>
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarNavDropdown"
aria-controls="navbarNavDropdown"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span className="navbar-toggler-icon" />
</button>
<div className="collapse navbar-collapse" id="navbarNavDropdown">
<ul className="navbar-nav">
<li className="nav-item active">
<a className="nav-link" href="#">
Home <span className="sr-only">(current)</span>
</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">
Features
</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">
Pricing
</a>
</li>
</ul>
</div>
<input className="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"></input>
<button className="btn btn-success m-2" type="submit">Search</button>
<h2><span className={this.getClass()}>
Total Quantity:
Total Price: {this.formatCount()}
</span></h2>
</nav>
</div>
);
}
getClass() {
let classes = "badge";
classes += this.state.totalPrice === 0 ? " badge-danger" : " badge-warning";
return classes;
}
formatCount() {
const { totalPrice } = this.state;
return totalPrice === 0 ? "Your Cart is Empty" : totalPrice+"€";
}
}
export default header;
主要
import React, { Component } from 'react';
import ProductInfo from '../plist.json';
import Product from './product'
class Products extends Component {
render() {
return (
<div className="container">
<div className="row ">
{ProductInfo.map(postDetail => <Product {...postDetail} />)}
</div>
</div>
)
}
}
export default Products
产品
import React, { Component } from 'react';
class Product extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
handleIncerement = () => {
this.setState({
count: this.state.count + 1
});
}
handleDecrement = () => {
if(this.state.count< 1){
this.setState({
count:0
});
}else {
this.setState({
count: this.state.count- 1
});
}
}
render() {
const { name, image, price, description } = this.props;
let totalQuantity= 0;
let totalPrice = 0;
totalQuantity += this.state.count;
totalPrice += this.state.count * {price};
console.log("Quantity:"+ totalQuantity);
console.log("Total Price:"+ totalPrice);
return (
<div className="col-md-4 ml-auto">
<img className="productpic" src={require(`./images/${image}`)} alt="Product" />
<h2 className="display-6"> <a href="{url}">{name}</a></h2>
<p className="h5 price">{price}</p>
<p className="info">{description}</p>
<div className="counter">
<button className="btn btn-info" onClick={this.handleIncerement}>+</button>
<div className="count">{this.state.count}</div>
<button className="btn btn-info" onClick={this.handleDecrement}>-</button>
</div>
</div>
);
}
}
export default Product
答案 0 :(得分:1)
我认为您在这里缺少React的概念。如果需要以下内容,则应在组件层次结构中保持较高的状态。
在此示例中,您需要在同级组件Main
中使用组件Header
中的某些内容。这意味着您应该具有将这些信息传递给他们的父组件。
例如,您可以拥有一个App
组件,该组件以某种方式采用JSON并将其与其他产品信息一起保持其状态:
// App.js
import React, { Component } from 'react'
import PRODUCTS from '../plist.json'
class App extends Component {
state = {
// here we are preparing the state copying all the
// information of a product plus a quantity property set to 0
products: PRODUCTS.map(p => ({ ...p, quantity: 0 }))
}
render() {
return (
<>
{/* here we should render the two components who needs data */}
<Footer />
</>
)
}
}
在render
方法中,我们可以渲染三个初始组件,但要进行一些更改...
首先,Header
需要总数量和总价格。 React最佳实践之一告诉我们,可以根据状态计算的所有内容都应该在状态之外。在这种情况下,我们不需要将这两个数量保存在状态中,因为我们可以轻松地计算它们:
// in App class definition
...
totalQuantity = () =>
this.state.products.reduce(
(sum, product) => sum + product.quantity,
0
)
totalPrice = () =>
this.state.products.reduce(
(sum, product) => sum + product.quantity * product.price,
0
)
...
为了能够计算这些值,我们将Header
组件的渲染添加到App
的渲染方法中:
// in App class definition
...
render() {
return (
<>
<Header quantity={ this.totalQuantity() }
price={ this.totalPrice() }
/>
{/* here we should render the Main component */}
<Footer />
</>
)
}
...
当然,您必须更改在Header
组件中呈现这些值的方式:
// Header component, render() method
// remember to apply some formatting for currency etc.
<span className={ this.getClass() }>
Total Quantity: { this.props.quantity }
Total Price: { this.props.price }
</span>
现在,让我们重新考虑一下Main
组件。它有两件事:
让我们将Main
添加到render方法中,然后使用以下功能:
// in App class definition
...
render() {
return (
<>
<Header quantity={ this.totalQuantity() }
price={ this.totalPrice() }
/>
<Main products={ this.state.products }
onIncrement={ this.handleIncrement }
onDecrement={ this.handleDecrement }
/>
{/* here we should render the Footer component */}
</>
)
}
...
在Main
组件中,我们需要更改呈现产品的方式,因为我们不再读取JSON,但是可以使用App
提供的数据。另外,我们需要能够传递增量和减量事件:
//主要
...
render(){ 返回( { this.props.products.map( (产品,索引)=> this.props.onIncrement(index)} onDecrement = {()=> this.props.onDecrement(index)} /> ) } ) }
...
在Product
组件中,我们现在不再需要内部状态,因为我们需要的所有内容都是作为道具提供的,因此它可以是无状态组件:
const Product = ({
image,
url,
name,
price,
description,
onIncrement,
quantity,
onDecrement
}) => (
<div className="col-md-4 ml-auto">
<img className="productpic"
src={ require(`./images/${image}`) }
alt="Product"
/>
<h2 className="display-6">
<a href="{url}">
{ name }
</a>
</h2>
<p className="h5 price">
{ price }
</p>
<p className="info">
{ description }
</p>
<div className="counter">
<button className="btn btn-info"
onClick={ onIncrement }>
+
</button>
<div className="count">
{ quantity }
</div>
<button className="btn btn-info"
onClick={ onDecrement }>
-
</button>
</div>
</div>
)
要完成此行为,我们需要处理App
组件中的增量和减量,以便更新状态并将更新的信息传播到Header
(数量和总数)和{{1 }}。
Main
我们几乎完成了您的// in App
...
handleIncrement = index =>
this.setState(prevState => ({
products: [
...prevState.products,
[index]: {
...prevState.products[index],
quantity: prevState.products[index].quantity + 1
}
]
}))
handleDecrement = index =>
this.setState(prevState => ({
products: [
...prevState.products,
[index]: {
...prevState.products[index],
quantity: prevState.products[index].quantity - 1
}
]
}))
...
中的index.js
组件的渲染:
App