Как рассчитать сумму предметов и общую стоимость с React?

JSDB , доступный для Linux, Windows и Mac, должен хорошо соответствовать счету. Он использует механизм Javascript Mozilla Spidermonkey и кажется, что это меньше хлопот для установки по сравнению с node.js (по крайней мере, в прошлый раз я попробовал node.js пару лет назад).

Я нашел JSDB из этого интересный список оболочек Javascript: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Shells

0
задан info perto 15 January 2019 в 16:46
поделиться

1 ответ

1128 Я думаю, что здесь вам не хватает концепции 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 в метод визуализации и затем поработаем над этими функциями:

// 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. Кроме того, мы должны иметь возможность передавать события увеличения и уменьшения:

// Main

...

render () {return ({this.props.products.map ((product, index) => 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 (количество и общее количество) и 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:

import React from "react";
import ReactDOM from "react-dom";
import App from "./components/app";
import './index.css';
import 'bootstrap/dist/css/bootstrap.css';


ReactDOM.render(<App />, document.getElementById("root"));
0
ответ дан 0xc14m1z 15 January 2019 в 16:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: