React 中来自 API 的状态

State from API in React

我正在执行一个可以修改产品价格的项目(从假货 API 中检索),然后单击一个按钮,我通过计算 20% 的增值税来更新。我遇到一个问题,我想要一个价格状态,在这个状态下,它是我输入的值,即 {listProduct.price},所以我的 API 的价格最初显示在输入(即第一篇文章 105.95 美元,...)但它不起作用。

您将首先找到显示产品页面的 productsDetails 部分的代码,以及从 API

检索数据的产品代码

如果您有任何我感兴趣的解决方案,请提前致谢。 (抱歉,我是 React 的新手,我仍然在为所有这些概念而苦苦挣扎)

产品详情

import React, { Component } from 'react'
import '../css/ProductsDetails.css'
import {AiOutlineArrowLeft} from "react-icons/ai";
import {Link} from 'react-router-dom'


export default class ProductsDetails extends Component {
    constructor(props) {
        super(props);
        this.state = {id: this.props.match.params.id, price: };
    }
    updatePrice = (e) => {
        console.log(e);
        this.setState({
            price: e.target.value
        })
    }

    render() {
        const {location: {state: {listProduct}}} = this.props;
        return (
            <div className="products__details">
                <Link to="/"><AiOutlineArrowLeft className="nav__arrow" /></Link>
                <h1 className="details__title">{listProduct.title}</h1>
                <div className="details__align--desk">
                    <div className="details__img">
                    <img className="product__img" src={listProduct.image} alt="Affichage du produit"/>
                    </div>
                    <div className="products__align--desk">
                        <h2 className="product__title">Description</h2>
                        <p className="product__description">{listProduct.description}</p>
                        <h2 className="product__title">Price</h2>
                        <form className="form__price">
                            <input className="input__price" type="text" value={listProduct.price} onChange={this.updatePrice} />
                            <p>Price (including VAT): {Math.round((listProduct.price + listProduct.price * 0.2)*100) /100} €</p>
                            <br/>
                            <input className="btn__update" type="submit" value="Update product" />
                        </form>
                    </div>
                    <div className="category__align--desk">
                        <h2 className="product__title">Category</h2>
                        <p className="product__category">{listProduct.category}</p>
                    </div>
                </div>
            </div>
        )
    } 
}

产品

import React, { Component } from 'react';
import '../css/Products.css';
import axios from 'axios';
import './ProductsDetails'
import {Link} from 'react-router-dom'

export default class Products extends Component {
    constructor(props) {
      super(props);
      this.state = {productsData: []};
    }
      componentDidMount = () => {
        axios.get('https://fakestoreapi.com/products?limit=7')
        .then(res => {
          console.log(res.data)
          this.setState ({
            productsData: res.data
          })
        })
      }
    render() {
        const listsProducts = this.state.productsData.map(listProduct => {
            return <tbody className="products__body">
                    <tr>
                        <td> <Link to={{pathname: "/products-details/" + listProduct.id,state: {listProduct}}}>{listProduct.title}</Link></td>
                        <td className="products__category">{listProduct.category}</td>
                        <td>{listProduct.price}</td>
                        <td>{Math.round((listProduct.price + listProduct.price * 0.2)*100) /100}</td>
                    </tr> 
              </tbody>
          })
        return (
            <main className="products">
                <h1 className="products__title">Products management</h1>
                <table cellSpacing="0">
                <thead className="products__head">
                    <tr>
                    <th className="table--title">Product name</th>
                    <th className="table--title">Category</th>
                    <th className="table--title">Price</th>
                    <th className="table--title">Price (including VAT)</th>
                    </tr>
                </thead>
                  {listsProducts}
                </table>
            </main>
        )
    }
}

由于您想在一个组件中显示一些数据并从另一个组件更新 that 数据,那么这里的解决方案是 Lift State Up。将产品状态和数据获取移动到 ProductsDetailsProducts 组件的共同祖先。

建议:

  1. 在父组件中声明productsData、数据获取和updatePrice处理程序。

    function App() {
      const [productsData, setProductsData] = useState([]);
    
      useEffect(() => {
        axios.get("https://fakestoreapi.com/products?limit=7").then((res) => {
          console.log(res.data);
          setProductsData(res.data);
        });
      }, []);
    
      const updatePrice = (id, price) => {
        setProductsData((productsData) =>
          productsData.map((product) =>
            product.id === Number(id)
              ? {
                  ...product,
                  price: Number(price)
                }
              : product
          )
        );
      };
    
      return (
        <div className="App">
          <Router>
            <Switch>
              <Route
                path="/products-details/:id"
                render={(props) => (
                  <ProductsDetails
                    products={productsData}
                    updatePrice={updatePrice}
                    {...props}
                  />
                )}
              />
              <Route path="/">
                <Products products={productsData} />
              </Route>
            </Switch>
          </Router>
        </div>
      );
    }
    
  2. 更新 Products 以使用来自父级的 products 道具。

    class Products extends Component {
      render() {
        const listsProducts = this.props.products.map((listProduct) => {
          return (
            <tbody className="products__body" key={listProduct.id}>
              <tr>
                <td>
                  {" "}
                  <Link
                    to={{
                      pathname: "/products-details/" + listProduct.id
                    }}
                  >
                    {listProduct.title}
                  </Link>
                </td>
                <td className="products__category">{listProduct.category}</td>
                <td>{Number(listProduct.price).toFixed(2)}</td>
                <td>
                  {Number(listProduct.price * 1.2).toFixed(2)} €
                </td>
              </tr>
            </tbody>
          );
        });
    
        return (
          <main className="products">
            <h1 className="products__title">Products management</h1>
            <table cellSpacing="0">
              <thead className="products__head">
                <tr>
                  <th className="table--title">Product name</th>
                  <th className="table--title">Category</th>
                  <th className="table--title">Price</th>
                  <th className="table--title">Price (including VAT)</th>
                </tr>
              </thead>
              {listsProducts}
            </table>
          </main>
        );
      }
    }
    
  3. 更新 ProductsDetails 以使用 productsupdatePrice 回调道具。为表单创建一个 submitHandler 以更新价格。对于输入,你会想要使用 defaultValue 道具,因为你想提供一个初始值,但 而不是 立即更改原始值数据。

    class ProductsDetails extends Component {
      constructor(props) {
        super(props);
        this.state = { id: this.props.match.params.id, price: 0 };
      }
    
      updatePrice = (e) => {
        console.log(e);
        this.setState({
          price: e.target.value
        });
      };
    
      submitHandler = (e) => {
        e.preventDefault();
        const {
          match: {
            params: { id }
          }
        } = this.props;
        this.props.updatePrice(id, this.state.price);
      };
    
      render() {
        const {
          match: {
            params: { id }
          },
          products
        } = this.props;
    
        const listProduct = products.find((product) => product.id === Number(id));
    
        return (
          <div className="products__details">
            <Link to="/">
              <AiOutlineArrowLeft className="nav__arrow" />
            </Link>
            <h1 className="details__title">{listProduct.title}</h1>
            <div className="details__align--desk">
              <div className="details__img">
                <img
                  className="product__img"
                  src={listProduct.image}
                  alt="Affichage du produit"
                />
              </div>
              <div className="products__align--desk">
                <h2 className="product__title">Description</h2>
                <p className="product__description">{listProduct.description}</p>
                <h2 className="product__title">Price</h2>
                <form className="form__price" onSubmit={this.submitHandler}>
                  <input
                    className="input__price"
                    type="text"
                    defaultValue={Number(listProduct.price).toFixed(2)}
                    onChange={this.updatePrice}
                  />
                  <p>
                    Price (including VAT):{" "}
                    {Number(listProduct.price * 1.2).toFixed(2)} €
                  </p>
                  <br />
                  <input
                    className="btn__update"
                    type="submit"
                    value="Update product"
                  />
                </form>
              </div>
              <div className="category__align--desk">
                <h2 className="product__title">Category</h2>
                <p className="product__category">{listProduct.category}</p>
              </div>
            </div>
          </div>
        );
      }
    }