简体   繁体   中英

Refresh page after submit form in React

When I change the price of my program in the input and I click on the update button, all is well the price changes but when I refresh my page I have an error that appears and even when I do not modify the price and I just refresh the page this error appears and I don't understand why

Here is the screenshot of the error and you will find my code below在此处输入图像描述

App

 import React, { useState, useEffect } from 'react'; import './css/App.css'; import './css/Products.css'; import axios from 'axios'; import Navigation from './Components/Navigation'; import Products from './Components/Products'; import {BrowserRouter as Router, Route, Switch,} from 'react-router-dom'; import ProductsDetails from './Components/ProductsDetails'; export default function App() { const [productsData, setProductsData] = useState([]); useEffect(() => { axios.get("https://fakestoreapi.com/products?limit=7").then((res) => { 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> <Navigation/> <Switch> <Route path="/products-details/:id" render={(props) => ( <ProductsDetails products={productsData} updatePrice={updatePrice} {...props} /> )} /> <Route path="/"> <Products products={productsData} /> </Route> </Switch> </Router> </div> ); }

Products

 import React, { Component } from 'react'; import '../css/Products.css'; import './ProductsDetails' import {Link} from 'react-router-dom' export default 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><p className={`${listProduct.category==="men's clothing"? "category__orange": "category__green"}`}>{listProduct.category}</p></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> ); } }

ProductsDetails

 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); // ajout de deux états l'id qu'on récupére de l'API et le prix qui vaut 0 this.state = { id: this.props.match.params.id, price: 0 }; } // mise en place d'une méthode qui permet de modifier la valeur dans l'input texte updatePrice = (e) => { console.log(e); this.setState({ price: e.target.value }); }; /* mise en place d'une méthode qui permet au clique du bouton de changer le prix grâce à la méthode "updatePrice ainsi que l'id et l'état du prix du produit */ submitHandler = (e) => { // permet au clique du bouton que concerver localement la valeur modifiée localStorage.setItem('price', this.state.price) e.preventDefault(); const { match: { params: { id } } } = this.props; this.props.updatePrice(id, this.state.price); }; // permet de garder la valeur modifiée au refresh de la page componentDidMount() { const price = localStorage.getItem('price') this.setState({price}); } render() { const { match: { params: { id } }, products } = this.props; // Ajout d'une variable qui récupére le premier id trouvé dans le tableau "products" 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 name="price" 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={`${listProduct.category==="men's clothing"? "category__orange": "category__green"} product__category`}>{listProduct.category}</p> </div> </div> </div> ); } }

I thank you in advance for your explanations

I suspect its because you're not covering a state when listProduct is null . When it loads, it immediately renders, as it's getting your product data, so products can be empty, and the .find() would return a null , then you're trying to render listProduct.title while it's null . Ideally, your render should check for listProduct being available or not.

Even better, have a few states of your component, like loading data, showing data, no data.

  <Card>
    { dataStatus === "Loaded" &&
      <Card.Title>{person.Name}</Card.Title>
    }
    { dataStatus === "Loading" &&
      <Card.Loader>Loading...</Card.Loader>
    }
    { dataStatus === "Error" &&
      <Card.Error>Sorry, we had an oopsie...</Card.Error>
    }
    { dataStatus === "Empty" &&
      <Card.Empty>Looks like we're missing something...</Card.Empty>
    }
  </Card>

Further explanation and code examples here: https://davidlozzi.com/2021/05/14/keeping-react-components-state-top-of-mind/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM