【问题标题】:React UseState hook for updating data - CRUD用于更新数据的 React UseState 钩子 - CRUD
【发布时间】:2021-04-10 16:41:07
【问题描述】:

我只是想知道是否有人能指出我的代码哪里出错了。 我对反应比较陌生,所以从一个简单的待办事项列表开始。 然后我对其进行了编辑以允许各种其他形式,例如菜单、配置文件等。 下面是菜单部分的附加代码。 如果我使用 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)}>&times;</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 仅识别一个参数,我只能想象当添加了多个表单字段/输入时,这就是中断的原因。不幸的是,我不知道是否有足够的反应。

【问题讨论】:

  • 好问题!您尝试过什么来解决您的问题?
  • 我根据以下答案更新了我的 useState 格式。这允许meet 编辑信息。如果我再次尝试编辑,表单中的信息仍然会更改,但是在刷新时,旧信息仍会从数据库中提取。新信息不会发送给它。 item_title 列中出现非空错误。检查命名约定并删除除一个以外的所有字段后,它确实有效,但只有标题或描述或价格。下面的 Olivier 说我的 setInputs 只接受一个参数,所以我想这就是原因。目前正在努力解决这个问题。
  • 您能否将您尝试的内容添加到您的问题中,而不是将其添加为评论?我相信 Olivier Boissé 的回答可能会奏效。他们在回答中建议使用对象作为您的输入。
  • 没问题。道歉。我更新了问题中的代码部分以反映 Olivier 建议的更改,并删除了 MenuList 代码,因为它似乎与问题无关。
  • 干杯。介意我问Overkill如何?我还没有设法找到解决方案,因为提供的答案没有奏效。任何帮助都可能使我朝着正确的方向前进。

标签: reactjs react-hooks crud use-state


【解决方案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} />

【讨论】:

  • 与另一个答案类似,当我将此修复程序与函数和 useEffect 一起应用时,我被返回“列“item_title”中的空值违反非空约束”的错误。表单中的信息本身会更新,但似乎没有发送到数据库。
  • 在您触发PUT http 请求时检查您的浏览器是否发送了输入值
  • 我刚看了一下,不是。
  • body 变量的值是多少?我编辑了我的答案,您的输入值可能有问题,请尝试value={title} 而不是value={menu.item_title}
  • 感谢您的帮助。它没有解决我的问题,但它确实让我思考它。最后,您对单个参数是正确的。一旦我明白了这一点,我就能够通过将我的 setInputs 拆分为单独的 useStates 到 setTitle、setDescription、setPrice 等来修复它。
【解决方案2】:

你应该这样设置你的状态:

  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 方法更改,另一方面,菜单对象中的值将保持相同的值。

【讨论】:

  • 谢天谢地,这让我可以编辑表单字段,但是,当我点击编辑时,我返回了一个错误,即“item_title”列中的空值违反了非空约束”,并且信息有只在数据库中没有改变表格。刷新后再次从数据库调用旧信息。
  • 如果列名是 item_title,您应该重命名输入中的字段以匹配该字段,我没有提及发送数据的任何内容,但是您当然需要设置正确的名称,我的回答是关于 useState 钩子,我希望这足够清楚
  • 它在发送单个字段(如标题或描述或价格)时有效,但不能发送多个字段。上面的 Olivier 告诉我,我的 setInputs 只需要一个参数,我想这就是为什么有多个不会工作的原因。我只能假设存在错误或我在某处的反应代码本身中做错了什么。
【解决方案3】:

我最终弄清楚了这个问题。 通过将我的 setInput useState 拆分为单独的单个 useState,我能够让它工作。

所以我的原始代码...

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 只允许一个参数。拆分它可以让我传递剩余的参数。 谢谢大家的帮助,希望有一天这也能帮助到其他人!

【讨论】:

    猜你喜欢
    • 2021-05-23
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2020-06-21
    • 2019-09-13
    • 2020-09-27
    • 2020-09-02
    相关资源
    最近更新 更多