简体   繁体   中英

How can i access the data from one useState in the next useState

Im trying to create a little marketplace website for a project which will use stripe Checkout. I've been following a tutorial however it didn't cover using products from an API. This is where i got stuck.

So firstly my table in the api which contains the product has these fields: oid | listingTitle | itemDescription | categorySelection | imageSelection | userEmail | userPhoneNumber

This all works perfectly however apart one thing. In the product useState im trying to use these fields from the database to store the name description and price which will then be sent to stripe itsel. However when sending the payment in the itemDescription it will say "undefined" the same in name etc. Apart from price because i set it to 80 just to test.

Now my question is how i can access the fields from the api with the info in the product useState i have my whole code below:

function Item({match}) {
    useEffect(() => {
        fetchItem();
        console.log(match)
    },[]);

const [item, setItem]= useState([]);
const fetchItem= async ()=>{
    const fetchItem= await fetch (`http://link //?oid=${match.params.oid}`
    );
    const item= await fetchItem.json();
    setItem(item.rows[0])
    console.log(item)

}
toast.configure()


  const [product] = useState({
    name: item.listingTitle,
    price: "80",
    description: item.itemDescription,
  });

 console.log(product.name)
  async function handleToken(token, addresses) {
    const response = await axios.post(
      "http://localhost:8080/checkout",
      { token, product }
    );
 
    console.log(response.status)
 
    if (response.status === 200) {
      toast("Success! Check email for details", { type: "success" });
    } else {
      toast("Something went wrong", { type: "error" });
    }
  }

  return (
    <div className="App">

      <div className="container">
      
        <h1 key={item.oid}></h1>
        <br />
        <br />
        <h1 className="text-center">Stripe Checkout</h1>
        <br />
        <h2 className="text-center">Product Info:</h2>
        <h3 className="text-center">Product Name: {item.listingTitle}</h3>
        <h3 className="text-center">Product Price: {item.itemPrice}</h3>
        <img className="image" src={[item.imageSelection]}width={250} height={150}></img>
        <h3 className="text-center">
          Product Description: {item.itemDescription}
        </h3>
        <br />
        <div className="form-group container">
          <StripeCheckout
            className="center"
            stripeKey=""
            token={handleToken}
            amount={item.itemPrice * 100}
            name={item.listingTitle}
            billingAddress
            shippingAddress
          />
          
        </div>
        
      </div>

    </div>
  );
}

this is the common problem every react newbies face, the problem here is setState functions dont update values instantly instead it gets submitted to react core system and later assigned to that state after all the codes executed so if you console.log a state in next line just after setting it you will get either old value or undefined thats why useEffect hook is here to help to track one state and use its value in other state you have to use useEffect hook like this ex: useEffect(()=>{},[stateToTrack])

here i have also written a demo in sandbox you can check and play hope this will help demo

import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const [item, setItem] = useState([]);

  function fetchItem() {
    fetch("https://jsonplaceholder.typicode.com/posts/1")
      .then((r) => r.json())
      .then((r) => {
        setItem(r);
      });
  }

  const [product, setProduct] = useState({
    name: "",
    desc: ""
  });

  useEffect(fetchItem, []); // run once

  useEffect(() => {
    // tracking item state
    setProduct({
      name: item.title,
      desc: item.body
    });
    console.log(item);
  }, [item]);

  return (
    <>
      <div style={{ fontSize: 20, fontWeight: "bold" }}>{product.name}</div>
      <br />
      <div>{product.desc}</div>
    </>
  );
}

Kinda fundamental feature of Javascript; if you don't know what it is, very important to go learn it. Essentially it "wraps" a function in it's local environment and lets it run somewhat-independently - for simplest example, (() => {fetchItem()}) simply returns an anonymous function to be run; (() => {fetchItem()})(); creates it and runs it.

You have other issues, so probably closer to this (assuming you only wanted to run toast.configure() once)

function Item({match}) {
    const [item, setItem]= useState([]);
    const [product, setProduct] = useState({
        name: item.listingTitle,
        price: "80",
        description: item.itemDescription,
    });


    useEffect(() => {
        toast.configure()
        (async () => {
            const fetchItem= await fetch (`http://link //?oid=${match.params.oid}`);
            const item= await fetchItem.json();
            setItem(item.rows[0])
            console.log(item)
        })();
        console.log(match)
    },[match]);


    console.log(product.name)
    async function handleToken(token, addresses) {
        const response = await axios.post(
            "http://localhost:8080/checkout",
            { token, product }
        );
 
        console.log(response.status)
 
        if (response.status === 200) {
        toast("Success! Check email for details", { type: "success" });
        } else {
        toast("Something went wrong", { type: "error" });
        }
  }

  return (
    <div className="App">

      <div className="container">
      
        <h1 key={item.oid}></h1>
        <br />
        <br />
        <h1 className="text-center">Stripe Checkout</h1>
        <br />
        <h2 className="text-center">Product Info:</h2>
        <h3 className="text-center">Product Name: {item.listingTitle}</h3>
        <h3 className="text-center">Product Price: {item.itemPrice}</h3>
        <img className="image" src={[item.imageSelection]}width={250} height={150}></img>
        <h3 className="text-center">
          Product Description: {item.itemDescription}
        </h3>
        <br />
        <div className="form-group container">
          <StripeCheckout
            className="center"
            stripeKey=""
            token={handleToken}
            amount={item.itemPrice * 100}
            name={item.listingTitle}
            billingAddress
            shippingAddress
          />
          
        </div>
        
      </div>

    </div>
  );
}

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