在反应中使用 useState 添加项目以订购的问题

Problem with adding item to order with useState in react

所以我正在构建我的第一个 React 应用程序,一个没有数据库的简单 e-commerce 站点。当我转到特定的书页时,我希望能够将该项目添加到只是 objects(产品,又名书)数组的订单中。但是我的函数 submitOrder 有一个问题,我不能使用 setBook(使用 useState)。

我在旁边添加了注释,以便于查看我的 app.js submitOrder 函数中哪里出了问题

App.js (parent)

import React, { useState } from "react";
import "./App.css";
import data from "./data/books.json";
import Main from "./Components/Main";
import Header from "./Components/Header";
import {
  BrowserRouter as Router,
  Link,
  Route,
  Switch,
  useParams,
} from "react-router-dom";
import Single from "./Components/Single";
// import Search from "./Components/Search";
import Checkout from "./Components/Checkout";

function App() {
  const [order, setOrder] = useState([{
    "isbn": "9781593275846",
    "title": "Harry Potter and the Methods of Rationality",
    "author": "Eliezer Yudkowsky",
    "publisher": "No Starch Press",
    "category": "Fantasy",
    "price": 19.99,
    "picture": "mor.jpg",
    "inventory": 10,
    "quantity": 1
  }]);
  let [newBook, setNewBook] = useState({})
  let [book, setBook] = useState({})
  const submitOrder = (e) => {
    e.preventDefault();
    console.log(e.target);
    console.log(e.target.quantity.value, e.target.obj.value);
    let id = e.target.obj.value;
    console.log(data[id]); ///////////////////////logs object correctly
    book = data[id];
    book.quantity = e.target.quantity.value;
    console.log(book);  //////////////////////////logs object correctly with updated value
    setNewBook(book);
    console.log(newBook);//////////////////////////logs empty object
    setOrder(...order, newBook);
    console.log(order);
  };

  return (
    <Router>
      <div className="App">
        <Header />
        <Switch>  
          <Route
            exact
            path="/"
            render={() => <Main order={order} />}
          />;


          <Route
            exact
            path="/:i"
            render={() => <Single submitOrder={submitOrder} order={order} />}
          />;
        </Switch>
      </div>
    </Router>
  );
}

export default App;

Single.js (child)

import React, { useState } from "react";
import data from "../data/books.json";
import {
  BrowserRouter as Router,
  Link,
  Route,
  useParams
} from "react-router-dom";
import "./single.css";
import Search from "./Search";

function importAll(r) {
  let images = {};
  r.keys().forEach((item, index) => {
    images[item.replace("./", "")] = r(item);
  });
  return images;
}

const Single = (props) => {
  const images = importAll(require.context("../images", false, /\.(jpe?g)$/));
  let id = useParams();
  let params = id.i;
  let book = data[params];
  console.log(book);
  let order = props.order;
  console.log(order);

  const handleChange = (e) => {
    setQuantity(e.target.value);
  };
  return (
    <div id="single">
      <Search order={order} />
      <div id="info">
        <h3>Title: {book.title} </h3>
        <p>
          Author: <em>{book.author}</em>
        </p>
        <p>Genre: {book.category}</p>
        <p>ISBN: {book.isbn}</p>
        <p>Publisher: {book.publisher}</p>
        <p>
          Price: <strong>{book.price}$</strong>
        </p>
        <p><u>{book.inventory}</u> left in stock</p>
        <form onSubmit={props.submitOrder}>
          Quantity
          <input
            type="text"
            name="quantity"
            id="quantity"
            onChange={handleChange}
            value={quantity}
          />
          <input type="hidden" value={params} name="obj" />
          {/* <select name="quantity">
            {for (let i = 0; i<book.inventory; {
              <option selected value="scifi">{i}</option>
            }}
            </select> */}
          <br></br><br />
          <input type="submit" value="Add to Cart" id="purch" />
        </form>
      </div>

      <img src={images[book.picture]} id="cover" alt="cover" />
      <Link to={`/`}>Back</Link><br></br>
    </div>
  );
}
export default Single;

此外,这不太重要,但最好的方法是在功能完成后(也就是在订单更新后)自动 link 用户转到不同的页面?

submitOrder 是一个闭包函数,它会从您创建 submitOrder 函数时看到 newBook

基本上是这样的:https://reactjs.org/docs/hooks-faq.html#why-am-i-seeing-stale-props-or-state-inside-my-function

您还可以 google 了解更多相关信息 react hooks stale closure

另外我建议不要做这些事情 book = data[id];,像这样改变 useEffect 变量是不好的做法,它们实际上应该是 const 个变量;