我正在创建一个用于创建网站主干的表单。因此,您需要能够创建元素,然后将这些元素的值发送到服务器。
我的想法是创建两个useState数组,每个数组都具有相同的对象键,其中一个数组是表单字段,另一个是发送到服务器的对象数据。
页面加载来自服务器的当前评论列表或一个空白评论,理论上这将填充第一个插入的评论。
我想要的是这些文本输入中的onChange方法,它在文本输入数组中查找自身的索引,然后使用该索引在字段响应数组中查找特定对象。
因此,基本上,如果您有30组输入字段,并更新编号29,它将使用目标值更新相应数组中的编号29。下面的on change方法适用于第一个输入,但一旦启动addReview(),存储在第二个数组中的值就会消失,并且只有rev数组中的第一个对象保留数据。
const [revArr, setRevArr] = useState([
{
reviewer: (
<input
type='text'
name='reviewer'
onChange={(e) => {
rev.map(() => {
const i = revArr.map((rev, i) => i);
let obj = {
reviewer: e.target.value,
review: rev[i].review,
date: rev[i].date,
pic: rev[i].pic,
};
rev[i] = obj;
console.log(firmObj);
});
}}
/>
),
date: (
<input
type='text'
name='date'
onChange={(e) => {
rev.map(() => {
const i = revArr.map((rev, i) => i);
let obj = {
reviewer: rev[i].reviewer,
review: rev[i].review,
date: e.target.value,
pic: rev[i].pic,
};
rev[i] = obj;
});
}}
/>
),
review: (
<input
type='text'
name='review'
onChange={(e) => {
rev.map(() => {
const i = revArr.map((rev, i) => i);
let obj = {
reviewer: rev[i].reviewer,
review: e.target.value,
date: rev[i].date,
pic: rev[i].pic,
};
rev[i] = obj;
});
}}
/>
),
pic: (
<input
type='text'
name='pic1'
onChange={(e) => {
rev.map(() => {
const i = revArr.map((rev, i) => i);
let obj = {
reviewer: rev[i].reviewer,
review: rev[i].review,
date: rev[i].date,
pic: e.target.value,
};
rev[i] = obj;
});
}}
/>
),
},
]);
const addReviewObj = () => {
setReviews([
...rev,
{
reviewer: "",
date: "",
review: "",
pic: "",
},
]);
setRevArr([
...revArr,
{
reviewer: (
<input
type='text'
name='reviewer'
onChange={(e) => {
rev.map(() => {
const i = revArr.map((rev, i) => i);
let obj = {
reviewer: e.target.value,
review: rev[i] ? rev[i].review : "",
date: rev[i] ? rev[i].date : "",
pic: rev[i] ? rev[i].pic : "",
};
rev[i] = obj;
});
}}
/>
),
date: (
<input
type='text'
name='date'
onChange={(e) => {
rev.map(() => {
const i = revArr.map((rev, i) => i);
let obj = {
reviewer: rev[i] ? rev[i].reviewer : "",
review: rev[i] ? rev[i].review : "",
date: e.target.value,
pic: rev[i] ? rev[i].pic : "",
};
rev[i] = obj;
});
}}
/>
),
review: (
<input
type='text'
name='review'
onChange={(e) => {
rev.map(() => {
const i = revArr.map((rev, i) => i);
let obj = {
reviewer: rev[i] ? rev[i].reviewer : "",
review: e.target.value,
date: rev[i] ? rev[i].date : "",
pic: rev[i] ? rev[i].pic : "",
};
rev[i] = obj;
});
}}
/>
),
pic: (
<input
type='text'
name='pic1'
onChange={(e) => {
rev.map(() => {
const i = revArr.map((rev, i) => i);
let obj = {
reviewer: rev[i] ? rev[i].reviewer : "",
review: rev[i] ? rev[i].review : "",
date: rev[i] ? rev[i].date : "",
pic: e.target.value,
};
rev[i] = obj;
});
}}
/>
),
},
]);
};
您的问题有点让人困惑,但听起来您想要一个具有动态行数的表单。每行具有固定数量的输入。
您可以将状态保持在单个对象数组中,映射到数组上以呈现每行输入。
输入onChange处理程序将把数组索引和事件传递给函数。
您可以从事件中获取值和输入名称,这些(以及数组索引)是设置新状态的足够信息。
import { useState } from "react";
export default function App() {
const emptyReview = {
reviewer: "",
review: ""
};
const [results, setResults] = useState([{ ... emptyReview }]);
const onChange = (i, e) => {
const { value, name } = e.currentTarget;
const newResults = [...results];
newResults[i] = {
...newResults[i],
[name]: value
};
setResults(newResults);
};
const addReview = () => {
const newResults = [...results, { ... emptyReview }];
setResults(newResults);
};
return (
<div className="App">
{results.map((result, i) => (
<div key={i}>
<div>
<label>
reviewer:
<input
value={result.reviewer}
name="reviewer"
onChange={(e) => onChange(i, e)}
/>
</label>
</div>
<div>
<label>
review:
<input
value={result.review}
name="review"
onChange={(e) => onChange(i, e)}
/>
</label>
</div>
<hr />
</div>
))}
<button onClick={addReview}>new review</button>
<pre>{JSON.stringify(results)}</pre>
</div>
);
}
奖金如果输入只是相同的文本输入,并且标签重复,则您甚至可以从外部映射中映射对象的键。这样,如果您需要添加额外的字段,您只需在一个位置执行此操作,emptyReview
对象。
{results.map((row, i) => (
<div key={i} className="row">
{Object.keys(row).map((key) => (
<label key={key}>
{key}
<input
value={row[key]}
name={key}
onChange={(e) => onChange(i, e)}
/>
</label>
))}
</div>
))}