在反应中使用 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
个变量;
所以我正在构建我的第一个 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
个变量;