我只是想知道是否有人可以指出我的代码哪里出了问题。 我对反应比较陌生,所以从一个简单的待办事项列表开始。 然后我编辑它以允许各种其他形式,如菜单、个人资料等。 下面是菜单部分的附加代码。 如果我使用 postmaster,我的后端就可以工作,这让我相信它是我的前端,特别是我的 useState。 我可以调用数据并在我的模式中查看它,但它出现了,但是,我似乎无法编辑表单字段中的特定数据和/或将其发布到我的数据库中。
任何帮助将不胜感激。
我在下面附上了我的代码。
import React, { Fragment, useState } from "react";
const EditMenu = ({ menu }) => {
//editText function
const [inputs, setInputs] = useState(menu.item_title, menu.item_price, menu.item_description, menu.item_category);
const { title, category, price, description } = inputs;
const onChange = e =>
setInputs({ ...inputs, [e.target.name]: e.target.value });
const editMenuItem = async (item_id) => {
try {
const body = { title, category, price, description };
const res = await fetch(`http://localhost:5000/menu/${item_id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body)
});
window.location = "/admin";
} catch (error) {
console.error(error.message);
}
};
return (
<Fragment>
<button type="button" className="btn btn-warning" data-toggle="modal" data-target={`#id${menu.item_id}`}>Edit</button>
{/*id = "id21"*/}
<div className="modal" id={`id${menu.item_id}`} onClick={() => setInputs(menu.item_title, menu.item_price, menu.item_description, menu.item_category)}>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title">Edit Menu</h4>
<button className="close btn-danger" data-dismiss="modal" onClick={() => setInputs(menu.item_title, menu.item_price, menu.item_description, menu.item_category)}>×</button>
</div>
<div className="modal-body">
<input type="text" name="title" placeholder="Title" className="form-control my-3" value={menu.item_title} onChange={e => onChange(e)} />
<input type="tel" name="price" placeholder="Price" className="form-control my-3" value={menu.item_price} onChange={e => onChange(e)} />
<input type="text" name="description" placeholder="Description" className="form-control my-3" value={menu.item_description} onChange={e => onChange(e)} />
<input type="text" name="category" placeholder="Category" className="form-control my-3" value={menu.item_category} onChange={e => onChange(e)} />
</div>
<div className="modal-footer">
<button type="button" className="btn btn-warning" data-dismiss="modal" onClick={() => editMenuItem(menu.item_id)}>Edit</button>
<button type="button" className="btn btn-danger" data-dismiss="modal" onClick={() => setInputs(menu.item_title, menu.item_price, menu.item_description, menu.item_category)}>Close</button>
</div>
</div>
</div>
</div>
</Fragment>
);
};
更新, 到目前为止,我已经使用以下答案尝试了各种建议的修复方法。 这两个修复都允许表单域是可编辑的,并且表单域中的信息会发生变化,因此在状态内也会发生变化,但不会将其发送到数据库。刷新页面后,旧信息从数据库中提取。
我发现,如果我删除了所有表单字段,但只有一个,它会成功更新并发送到数据库。 标题或描述或价格或类别。 在更新时检查浏览器中的网络选项卡显示,对于多个输入字段,放置请求失败并且没有信息/有效负载发送到请求选项卡中的正文。
因此,数据库返回 NOT NULL 错误。 根据下面 Oliviers 的回答,setInput 只能识别一个参数,我只能想象当添加了多个表单字段/输入时,这是破坏性的。不幸的是,我不知道足够的反应来知道是否是这种情况。
答案 0 :(得分:1)
我发现你的状态初始化有问题 => const [inputs, setInputs] = useState(menu.item_title, menu.item_price, menu.item_description, menu.item_category);
不正确,useState
只带一个参数,这里你必须构建一个代表输入的对象。
这是一个使用函数初始化inputs
状态的解决方案,以防止每次重新渲染组件时计算对象
function buildInputs(menu) {
return {
title: menu.item_title,
category: menu.item_category,
price: menu.item_price,
description: menu.item_description
};
}
const EditMenu = ({ menu }) => {
//editText function
const [inputs, setInputs] = useState(() => buildInputs(menu));
const { title, category, price, description } = inputs;
// Needed if you want the inputs to be updtated when the menu property is updated
useEffect(() => setInputs(buildInputs(menu)), [menu]);
const onChange = e => setInputs({ ...inputs, [e.target.name]: e.target.value });
...
您还必须更改输入值以反映状态变量:
<input type="text" name="title" placeholder="Title"
className="form-control my-3" value={title} onChange={onChange} />
答案 1 :(得分:0)
你应该像这样设置你的状态:
const [inputs, setInputs] = useState({
title: menu.item_title,
price: menu.item_price,
category: menu.item_category,
description: menu.item_description
});
您还需要将值属性更改为变量而不是将它们设置为菜单值,例如:
//code
<input name="title" value={inputs.title} onChange={onChange}/>
因为您的 onChange 方法可以更改输入中的值,另一方面,菜单对象中的值将保持相同的值。
答案 2 :(得分:0)
我终于解决了这个问题。 通过将我的 setInput useState 拆分为单独的 useStates,我能够让它工作。
所以我的原始代码...
const EditMenu = ({ menu }) => {
const [inputs, setInputs] = useState(menu.item_title, menu.item_price, menu.item_description, menu.item_category);
const { title, category, price, description } = inputs;
改成这个了。
const EditMenu = ({ menu }) => {
const [item_title, setTitle] = useState(menu.item_title);
const [item_price, setPrice] = useState(menu.item_price);
const [item_description, setDescription] = useState(menu.item_description);
以及 onChange 函数和表单输入...
const onChange = e =>
setInputs({ ...inputs, [e.target.name]: e.target.value });
<input... onChange={e => onChange(e)} />
改成这个...
value={item_title} onChange={e => setTitle(e.target.value)} />
value={item_price} onChange={e => setPrice(e.target.value)} />
value={item_description} onChange={e => setDescription(e.target.value)} />
最后,即使解决方案对我不起作用,Oliviers 的推理还是正确的。我的 setInput 只允许一个参数。拆分它允许我传递剩余的参数。 谢谢大家的帮助,希望有一天这也能帮助别人!