如何在下一个 useState 中访问一个 useState 的数据

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

我正在尝试为将使用 stripe Checkout 的项目创建一个小型市场网站。我一直在学习教程,但它没有涵盖使用来自 API 的产品。这就是我卡住的地方。

所以首先我的 table 在包含产品的 api 中有这些字段:oid |上市标题 |项目描述 |类别选择 |图片选择 |用户邮箱 |用户电话号码

这一切都完美无缺,但有一点不同。在产品 useState 中,我试图使用数据库中的这些字段来存储名称描述和价格,然后将其发送到 stripe itsel。但是,当在 itemDescription 中发送付款时,它会在名称等方面显示相同的“未定义”。除了价格,因为我将其设置为 80 只是为了测试。

现在我的问题是如何使用产品 useState 中的信息访问 api 中的字段 我的整个代码如下:

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>
  );
}

这是每个 React 新手都面临的常见问题,这里的问题是 setState 函数不会立即更新值,而是将其提交给 React 核心系统,然后在所有代码执行后分配给该状态,所以如果您 console.log 设置后下一行的状态,您将获得旧值或未定义 这就是为什么 useEffect 钩子在这里提供帮助 要跟踪一个状态并在其他状态下使用它的值,您必须像这样使用 useEffect 挂钩,例如:useEffect(()=>{},[stateToTrack])

这里我也写了一个沙盒demo大家可以看看玩 希望这会有所帮助 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>
    </>
  );
}

有点Javascript的基本特征;如果您不知道它是什么,那么去学习它非常重要。本质上它在它的本地环境中“包装”了一个函数并让它 运行 somewhat-independently - 对于最简单的例子,(() => {fetchItem()}) 只是 returns 一个匿名函数 运行 ; (() => {fetchItem()})(); 创建它并 运行 保存它。

你还有其他问题,所以可能更接近这个(假设你只想 运行 toast.configure() 一次)

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>
  );
}