英文:
How to pass key:value onChange from select-option in reactjs?
问题
我遵循了这个教程并尝试进行了一些修改。
我有这段代码 addRequestForm.js
:
import { BiPlus } from 'react-icons/bi'
import { useMutation, useQueryClient } from "react-query"
import { addRequest, getRequests } from "../../lib/helper"
import Bug from "./bugRequest"
import Success from "./successRequest"
export default function AddRequestForm({ formData, setFormData }) {
const queryClient = useQueryClient()
const addMutation = useMutation(addRequest, {
onSuccess: () => {
queryClient.prefetchQuery('requests', getRequests)
}
})
const handleSubmit = (e) => {
e.preventDefault();
if (Object.keys(formData).length == 0) return console.log("Don't have Form Data");
let { sector, contact_name } = formData;
const model = {
sector, contact_name
}
addMutation.mutate(model)
}
if (addMutation.isLoading) return <div>Loading!</div>
if (addMutation.isError) return <Bug message={addMutation.error.message}></Bug>
if (addMutation.isSuccess) return <Success message={"Added Successfully"}></Success>
return (
<form className="grid lg:grid-cols-2 w-4/6 gap-4 md:px-4 md:mx-auto" onSubmit={handleSubmit}>
<div className="input-type">
<label htmlFor="sector" className="block text-sm font-medium text-gray-700">
Sector
</label>
<select
id="sector"
name="sector"
autoComplete="sector-name"
className="border w-full px-5 py-3 focus:outline-none rounded-md"
onChange={(e) => setFormData({ [e.target.name]: e.target.value })}
>
<option value="North">North</option>
<option value="South">South</option>
<option value="West">West</option>
<option value="East">East</option>
</select>
</div>
<div className="form-control input-type">
<label className="input-group">
<span>Contact Name</span>
<input type="text" onChange={setFormData} name="contact_name" placeholder="Contact Name Here.." className="w-full input input-bordered" />
</label>
</div>
<button type="submit" className="flex justify-center text-md w-2/6 bg-green-500 text-white px-4 py-2 border rounded-md hover:bg-gray-50 hover:border-green-500 hover:text-green-500">
Add <span className="px-1"><BiPlus size={24}></BiPlus></span>
</button>
</form>
)
}
对于 name="contact_name"
,已成功插入到数据库(mongodb + mongoose)。但是,我仍然困惑如何对 select
元素执行相同的操作。
已尝试以下操作:
onChange={(e) => setFormData({ e.target.name: e.target.value })}
onChange={(e) => setFormData({ sector.name: e.target.value })}
onChange={(e) => setFormData({ [e.target.name][0]: e.target.value })}
出现语法错误:Unexpected token,expected ","。虽然我认为这是正确的值,当我将其打印出来时(结果:"sector:myname")。
onChange={(e) => setFormData({ sector: e.target.value })}
onChange={(e) => setFormData({ [e.target.name]: e.target.value })}
没有插入到数据库。
如何正确编写它?我正在使用 Next.js(我认为与 React.js 相同,对吗?)+ @reduxjs/toolkit 1.9.1。
如果需要,这是 reducer.js
:
import UpdateRequestForm from "./updateRequestForm";
import AddRequestForm from "./addRequestForm";
import { useSelector } from "react-redux";
import { useReducer } from "react";
const formReducer = (state, event) => {
return {
...state,
[event.target?.name]: event.target?.value
}
}
export default function FormRequest() {
const [formData, setFormData] = useReducer(formReducer, {})
const formId = useSelector((state) => state.app.client.formId)
return (
<div className="container mx-auto py-5">
{formId ? UpdateRequestForm({ formId, formData, setFormData }) : AddRequestForm({ formData, setFormData })}
</div>
)
}
英文:
I follow this tutorial and try to modify it a little.
I have this code addRequestForm.js
import { BiPlus } from 'react-icons/bi'
import { useMutation, useQueryClient } from "react-query"
import { addRequest, getRequests } from "../../lib/helper"
import Bug from "./bugRequest"
import Success from "./successRequest"
export default function AddRequestForm({ formData, setFormData }) {
const queryClient = useQueryClient()
const addMutation = useMutation(addRequest, {
onSuccess: () => {
queryClient.prefetchQuery('requests', getRequests)
}
})
const handleSubmit = (e) => {
e.preventDefault();
if (Object.keys(formData).length == 0) return console.log("Don't have Form Data");
let { sector, contact_name } = formData;
const model = {
sector, contact_name
}
addMutation.mutate(model)
}
if (addMutation.isLoading) return <div>Loading!</div>
if (addMutation.isError) return <Bug message={addMutation.error.message}></Bug>
if (addMutation.isSuccess) return <Success message={"Added Successfully"}></Success>
return (
<form className="grid lg:grid-cols-2 w-4/6 gap-4 md:px-4 md:mx-auto" onSubmit={handleSubmit}>
<div className="input-type">
<label htmlFor="sector" className="block text-sm font-medium text-gray-700">
Sector
</label>
<select
id="sector"
name="sector"
autoComplete="sector-name"
className="border w-full px-5 py-3 focus:outline-none rounded-md"
onChange={(e) => setFormData({ [e.target.name]: e.target.value })}
>
<option value="North">North</option>
<option value="South">South</option>
<option value="West">West</option>
<option value="East">East</option>
{/* */}
</select>
</div>
<div className="form-control input-type">
<label className="input-group">
<span>Contact Name</span>
<input type="text" onChange={setFormData} name="contact_name" placeholder="Contact Name Here..“ className="w-full input input-bordered" />
</label>
</div>
<button type="submit" className="flex justify-center text-md w-2/6 bg-green-500 text-white px-4 py-2 border rounded-md hover:bg-gray-50 hover:border-green-500 hover:text-green-500">
Add <span className="px-1"><BiPlus size={24}></BiPlus></span>
</button>
</form >
)
}
For name=“contact_name” already succeed insert into database (mongodb + mongoose). But, I’m still confuse, how to do the same to select-option?
Already tried these:
onChange={(e) => setFormData({ e.target.name: e.target.value })}
onChange={(e) => setFormData({ sector.name: e.target.value })}
onChange={(e) => setFormData({ [e.target.name][0]: e.target.value })}
Got Syntax error: Unexpected token, expected ",". While I thought this is the right value when I’m consoling these ( result: “sector:myname”).
onChange={(e) => setFormData({ sector: e.target.value })}
onChange={(e) => setFormData({ [e.target.name]: e.target.value })}
No insert into database.
How to write it correctly? I’m using nextjs (i thought the same with reactjs, right?) + @reduxjs/toolkit 1.9.1.
In case needed, here is reducer.js:
import UpdateRequestForm from "./updateRequestForm";
import AddRequestForm from "./addRequestForm";
import { useSelector } from "react-redux";
import { useReducer } from "react";
const formReducer = (state, event) => {
return {
...state,
[event.target?.name]: event.target?.value
}
}
export default function FormRequest() {
const [formData, setFormData] = useReducer(formReducer, {})
const formId = useSelector((state) => state.app.client.formId)
return (
<div className="container mx-auto py-5">
{formId ? UpdateRequestForm({ formId, formData, setFormData }) : AddRequestForm({ formData, setFormData })}
</div>
)
}
答案1
得分: 0
onChange = {(e) => {
let obj = {} ;
obj[e.target.name] = e.target.value;
setFormData(obj);
}
}
英文:
try this
onChange = {(e) => {
let obj = {} ;
obj[e.target.name] = e.target.value;
setFormData(obj);
}
}
答案2
得分: 0
我并不完全理解您对reducer的使用情况,但您可以用以下的简单handleChange函数来替代它。只是一个小提示,调用setFormData(//newData)
会完全擦除其中的内容,所以我们首先要展开原始状态,并根据key
来更改值。
状态和handleChange函数:
const [formData, setFormData] = React.useState({
sector: "North",
contact_name: ""
});
const handleChange = ({ target }) => {
// 解构目标对象
// 从目标对象中解构名称和值
const { name, value } = target;
// 设置状态
setFormData((previousState) => ({
...previousState,
[name]: value,
}));
};
用法:
<select
placeholder="选择一个部门"
name="sector"
value={formData.sector}
onChange={handleChange}
>
<option value="North">北部</option>
<option value="South">南部</option>
<option value="West">西部</option>
<option value="East">东部</option>
</select>
<input
value={formData.contact_name}
placeholder="联系人姓名"
name="contact_name"
onChange={handleChange}
/>
此外,请注意您需要为输入元素指定一个名称。在示例中,名称设置为sector。因为名称值将用于指示必须更新状态对象中的哪个键。
拥有受控输入字段是一种良好的做法。因此,将输入的值设置为状态将实现这一点。唯一需要记住的是您需要一个默认状态。如果您想查看,我已将所有内容添加到了codesandbox中。
英文:
I'm not entirely following your use case for the reducer but you could replace it with a simple handleChange function as follows. Just a side note, calling setFormData(//newData)
will complete erase what is in there so we first spread the original state and change the value based on the key
.
State and handleChange:
const [formData, setFormData] = React.useState({
sector: "North",
contact_name: ""
});
const handleChange = ({ target }) => {
// Deconstruct the target
// Deconstruct the name and value from the target
const { name, value } = target;
// Set the state
setFormData((previousState) => ({
...previousState,
[name]: value,
}));
};
Usage:
<select
placeholder="Select a sector"
name="sector"
value={formData.sector}
onChange={handleChange}
>
<option value="North">North</option>
<option value="South">South</option>
<option value="West">West</option>
<option value="East">East</option>
</select>
<input
value={formData.contact_name}
placeholder="Contact Name"
name="contact_name"
onChange={handleChange}
/>
A codesandbox : https://codesandbox.io/s/interesting-kilby-emcyl4?file=/src/App.js:461-615
Also note that you will need to assign a name to the input element. In the example, name is set to sector. As the name value will be used to indicate which key in the state object must be updated.
It's good practice to have controlled input fields. So setting the value of the input to your state will accomplish this. Only thing to remember is you need a default state. I have added it all to the codesandbox if you would like to take a look.
答案3
得分: 0
在我的情况下,只需使用以下语法:
…
value={formData.sector}
onChange={setFormData}
…
案件关闭。
英文:
In my case, just use this syntax:
…
value={formData.sector}
onChange={setFormData}
…
Case closed.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论