如何根据用户输入将对象推送到状态数组
how to push an object to a state array based on user input
我有一个 table 每行都有文本框,我想识别它们中的每一个
我需要将“task”和“setTask”从简单的字符串更改为一个对象数组,该数组可以为每一行获取用户输入并将其添加为对象 {id, value}(稍后使用)
这是一个工作示例:https://codesandbox.io/s/dawn-wildflower-cfvol?file=/src/App.js
- 单击“开始扫描”按钮(它将加载网格)
- 点击“写一个任务名称”中的任何一个(它将打开所有记录)
我需要的是:只为特定记录打开,handleChange 需要将对象推入数组而不是字符串
代码:
import { useState } from "react";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import { makeStyles, withStyles } from "@material-ui/core/styles";
import { Typography } from "@material-ui/core";
import Button from "@material-ui/core/Button";
const useStyles = makeStyles((theme) => ({
container: {
maxHeight: 440,
width: "100%"
},
}));
const StyledTableCell = withStyles((theme) => ({
head: {
backgroundColor: theme.palette.common.black,
color: theme.palette.common.white
},
body: {
fontSize: 14
}
}))(TableCell);
const StyledTableRow = withStyles((theme) => ({
root: {
"&:nth-of-type(odd)": {
backgroundColor: theme.palette.action.hover
}
}
}))(TableRow);
export default function CommentTest(
) {
const classes = useStyles();
const [bulkScanList, setBulkScanList] = useState([]);
const [name, setname] = useState([]);
const [openId, setOpenId] = useState();
const [editMode, setEditMode] = useState(false);
const [task, setTask] = useState("");
const data = {
samples: [
{
sampleContainers: [
{
id: 4447,
sampleId: 2656,
code: "00JC",
color: "Green",
name: "250g Soil Jar",
description: "250g Soil Jar",
containerId: 1,
comments: "",
barcode: "00JC001180",
testLists: null,
isStandardContainer: true,
preservationType: "none",
scanStatus: 1,
srComments: null
}
],
id: 2656,
batchId: 1499,
sampleName: "COC_SCA",
dateSampled: "2021-12-21T10:46:00",
matrixId: 2
},
{
sampleContainers: [
{
id: 4448,
sampleId: 2657,
code: "00JC",
color: "Green",
name: "250g Soil Jar",
description: "250g Soil Jar",
containerId: 1,
comments: "",
barcode: "00JC001182",
testLists: null,
isStandardContainer: true,
preservationType: "none",
scanStatus: 1,
srComments: null
}
],
id: 2657,
batchId: 1499,
sampleName: "COC_SCA",
dateSampled: "2021-12-21T10:46:00",
matrixId: 2
},
{
sampleContainers: [
{
id: 4449,
sampleId: 2658,
code: "00JC",
color: "Green",
name: "250g Soil Jar",
description: "250g Soil Jar",
containerId: 1,
comments: "",
barcode: "00JC001179",
testLists: null,
isStandardContainer: true,
preservationType: "none",
scanStatus: null,
srComments: "check"
}
],
id: 2658,
batchId: 1499,
sampleName: "COC_SCA",
dateSampled: "2021-12-21T10:46:00",
matrixId: 2
},
{
sampleContainers: [
{
id: 4450,
sampleId: 2659,
code: "00JC",
color: "Green",
name: "250g Soil Jar",
description: "250g Soil Jar",
containerId: 1,
comments: "",
barcode: "00JC001181",
testLists: null,
isStandardContainer: true,
preservationType: "none",
scanStatus: null,
srComments: "comment"
}
],
id: 2659,
batchId: 1499,
sampleName: "COC_SCA",
dateSampled: "2021-12-21T10:46:00",
matrixId: 2
},
{
sampleContainers: [
{
id: 4451,
sampleId: 2660,
code: "00JC",
color: "Green",
name: "250g Soil Jar",
description: "250g Soil Jar",
containerId: 1,
comments: "",
barcode: "00JC001183",
testLists: null,
isStandardContainer: true,
preservationType: "none",
scanStatus: null,
srComments: null
}
],
id: 2660,
batchId: 1499,
sampleName: "COC_SCA",
dateSampled: "2021-12-21T10:46:00",
matrixId: 2
}
]
};
const handleKeyDown = (event, type) => {
// Handle when key is pressed
};
const retrieveBulkScanList = (e) => {
const sampleNames = data?.samples.map((x) => ({
name: x.sampleName,
id: x.id
}));
const containers = data?.samples
.map((x) => x.sampleContainers)
.flat()
.map((elm) => elm);
console.log('retrieve bulk scan');
setname([...sampleNames]);
setBulkScanList([...containers]);
};
const handleChange = (e, container) => {
const { value, id } = e.currentTarget;
setTask(value);
console.log("comments added: " + value + " id: " + id);
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<TableContainer className={classes.container}>
<Table className={classes.table} stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
<TableCell>
<Typography variant="h6">Sample Name</Typography>
</TableCell>
<TableCell align="right">
<Typography variant="h6">Container Name</Typography>
</TableCell>
<TableCell align="right">
<Typography variant="h6">SR Comments</Typography>
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{bulkScanList.length === 0 ? (
<div>Scan to fetch data...</div>
) : (
bulkScanList
.slice(0)
.reverse()
.map((x) => (
<StyledTableRow key={x.id.toString()}>
<StyledTableCell component="th" scope="row">
{name
.filter((n) => n.id === x.sampleId)
.map((e) => e.name)}
_{x.sampleId}
</StyledTableCell>
<StyledTableCell align="right">{x.name}</StyledTableCell>
<StyledTableCell>
{editMode ? (
<div
onBlur={() => setEditMode(false)}
onKeyDown={e => handleKeyDown(e, "input")}
>
<input
type="text"
name="task"
placeholder="Write a task name"
value={task}
onChange={e => handleChange(e, x)}
/>
</div>
) : (
<div
onClick={() => setEditMode(true)}
>
<span>
{task || "Write a task name" || "Editable content"}
</span>
</div>
)}
</StyledTableCell>
</StyledTableRow>
))
)}
</TableBody>
</Table>
</TableContainer>
<Button
color="primary"
style={{ height: "50%", borderRadius: "30px" }}
onClick={retrieveBulkScanList}
>
Start Scan
</Button>
</div>
);
}
要将一个对象推送到一个已经存在的状态数组,您可以使用:
setState((oldArray) => [...oldArray, newObj]);
要映射对象的完整状态数组,您可以使用:
{state && state.map(({ id, value}) => (
<div>{id}</div>
<div>{value}</div>
))}
我终于解决了..这是一个工作代码示例https://codesandbox.io/s/happy-framework-e27gl?file=/src/App.js
基本上我改了4个地方
将 更改为以下内容
{
Object.values(task).filter((c) => c.id == x.id).length > 0 ?
Object.values(task).filter((c) => c.id == x.id).map(obj =>
<input
id={x.id}
type="text"
name="task"
placeholder="Write a task name"
value={obj.value}
onChange={e => handleChange(e, x)}
/>)
:
<input
id={x.id}
type="text"
name="task"
placeholder="I am duplicate"
onChange={e => handleChange(e, x)}
/>
}
更改{任务|| “写一个任务名称……”到下面
<span>{
Object.values(task).filter((c) => c.id == x.id).length > 0 ?
Object.values(task).filter((c) => c.id == x.id).map(obj =>
obj.value) : "I am the span" }
</span>
这个问题花了我一整天的时间来排序,因为 jsx 没有指出正确的错误,我继续修复其他地方..它只是给我以下错误
Error: Objects are not valid as a React child (found: object with keys {id, value}).
P.S: 另外我在我的代码中用 obj 替换了 {id, value}
这个很直接
const [task, setTask] = useState([]);
这就是魔法! (虽然很麻烦)
const handleChange = (e, container) => {
const { value, id } = e.currentTarget;
const oldArray = Object.values(task);
const pos = oldArray.map(function(e) { return e.id; }).indexOf(container.id);
console.log('position: ' + pos);
const matched = oldArray.filter(c => c.id === container.id);
if(matched.length > 0){
oldArray[pos] = {"id": container.id, "value":value};
setTask(oldArray);
console.log("hey")
}
else{
var newStateArray = oldArray.slice();
newStateArray.push({"id": container.id, "value":value});
setTask(newStateArray);
console.log("comments added: " + value + " id: " + container.id);
}
}
我有一个 table 每行都有文本框,我想识别它们中的每一个
我需要将“task”和“setTask”从简单的字符串更改为一个对象数组,该数组可以为每一行获取用户输入并将其添加为对象 {id, value}(稍后使用)
这是一个工作示例:https://codesandbox.io/s/dawn-wildflower-cfvol?file=/src/App.js
- 单击“开始扫描”按钮(它将加载网格)
- 点击“写一个任务名称”中的任何一个(它将打开所有记录)
我需要的是:只为特定记录打开,handleChange 需要将对象推入数组而不是字符串
代码:
import { useState } from "react";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import { makeStyles, withStyles } from "@material-ui/core/styles";
import { Typography } from "@material-ui/core";
import Button from "@material-ui/core/Button";
const useStyles = makeStyles((theme) => ({
container: {
maxHeight: 440,
width: "100%"
},
}));
const StyledTableCell = withStyles((theme) => ({
head: {
backgroundColor: theme.palette.common.black,
color: theme.palette.common.white
},
body: {
fontSize: 14
}
}))(TableCell);
const StyledTableRow = withStyles((theme) => ({
root: {
"&:nth-of-type(odd)": {
backgroundColor: theme.palette.action.hover
}
}
}))(TableRow);
export default function CommentTest(
) {
const classes = useStyles();
const [bulkScanList, setBulkScanList] = useState([]);
const [name, setname] = useState([]);
const [openId, setOpenId] = useState();
const [editMode, setEditMode] = useState(false);
const [task, setTask] = useState("");
const data = {
samples: [
{
sampleContainers: [
{
id: 4447,
sampleId: 2656,
code: "00JC",
color: "Green",
name: "250g Soil Jar",
description: "250g Soil Jar",
containerId: 1,
comments: "",
barcode: "00JC001180",
testLists: null,
isStandardContainer: true,
preservationType: "none",
scanStatus: 1,
srComments: null
}
],
id: 2656,
batchId: 1499,
sampleName: "COC_SCA",
dateSampled: "2021-12-21T10:46:00",
matrixId: 2
},
{
sampleContainers: [
{
id: 4448,
sampleId: 2657,
code: "00JC",
color: "Green",
name: "250g Soil Jar",
description: "250g Soil Jar",
containerId: 1,
comments: "",
barcode: "00JC001182",
testLists: null,
isStandardContainer: true,
preservationType: "none",
scanStatus: 1,
srComments: null
}
],
id: 2657,
batchId: 1499,
sampleName: "COC_SCA",
dateSampled: "2021-12-21T10:46:00",
matrixId: 2
},
{
sampleContainers: [
{
id: 4449,
sampleId: 2658,
code: "00JC",
color: "Green",
name: "250g Soil Jar",
description: "250g Soil Jar",
containerId: 1,
comments: "",
barcode: "00JC001179",
testLists: null,
isStandardContainer: true,
preservationType: "none",
scanStatus: null,
srComments: "check"
}
],
id: 2658,
batchId: 1499,
sampleName: "COC_SCA",
dateSampled: "2021-12-21T10:46:00",
matrixId: 2
},
{
sampleContainers: [
{
id: 4450,
sampleId: 2659,
code: "00JC",
color: "Green",
name: "250g Soil Jar",
description: "250g Soil Jar",
containerId: 1,
comments: "",
barcode: "00JC001181",
testLists: null,
isStandardContainer: true,
preservationType: "none",
scanStatus: null,
srComments: "comment"
}
],
id: 2659,
batchId: 1499,
sampleName: "COC_SCA",
dateSampled: "2021-12-21T10:46:00",
matrixId: 2
},
{
sampleContainers: [
{
id: 4451,
sampleId: 2660,
code: "00JC",
color: "Green",
name: "250g Soil Jar",
description: "250g Soil Jar",
containerId: 1,
comments: "",
barcode: "00JC001183",
testLists: null,
isStandardContainer: true,
preservationType: "none",
scanStatus: null,
srComments: null
}
],
id: 2660,
batchId: 1499,
sampleName: "COC_SCA",
dateSampled: "2021-12-21T10:46:00",
matrixId: 2
}
]
};
const handleKeyDown = (event, type) => {
// Handle when key is pressed
};
const retrieveBulkScanList = (e) => {
const sampleNames = data?.samples.map((x) => ({
name: x.sampleName,
id: x.id
}));
const containers = data?.samples
.map((x) => x.sampleContainers)
.flat()
.map((elm) => elm);
console.log('retrieve bulk scan');
setname([...sampleNames]);
setBulkScanList([...containers]);
};
const handleChange = (e, container) => {
const { value, id } = e.currentTarget;
setTask(value);
console.log("comments added: " + value + " id: " + id);
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<TableContainer className={classes.container}>
<Table className={classes.table} stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
<TableCell>
<Typography variant="h6">Sample Name</Typography>
</TableCell>
<TableCell align="right">
<Typography variant="h6">Container Name</Typography>
</TableCell>
<TableCell align="right">
<Typography variant="h6">SR Comments</Typography>
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{bulkScanList.length === 0 ? (
<div>Scan to fetch data...</div>
) : (
bulkScanList
.slice(0)
.reverse()
.map((x) => (
<StyledTableRow key={x.id.toString()}>
<StyledTableCell component="th" scope="row">
{name
.filter((n) => n.id === x.sampleId)
.map((e) => e.name)}
_{x.sampleId}
</StyledTableCell>
<StyledTableCell align="right">{x.name}</StyledTableCell>
<StyledTableCell>
{editMode ? (
<div
onBlur={() => setEditMode(false)}
onKeyDown={e => handleKeyDown(e, "input")}
>
<input
type="text"
name="task"
placeholder="Write a task name"
value={task}
onChange={e => handleChange(e, x)}
/>
</div>
) : (
<div
onClick={() => setEditMode(true)}
>
<span>
{task || "Write a task name" || "Editable content"}
</span>
</div>
)}
</StyledTableCell>
</StyledTableRow>
))
)}
</TableBody>
</Table>
</TableContainer>
<Button
color="primary"
style={{ height: "50%", borderRadius: "30px" }}
onClick={retrieveBulkScanList}
>
Start Scan
</Button>
</div>
);
}
要将一个对象推送到一个已经存在的状态数组,您可以使用:
setState((oldArray) => [...oldArray, newObj]);
要映射对象的完整状态数组,您可以使用:
{state && state.map(({ id, value}) => (
<div>{id}</div>
<div>{value}</div>
))}
我终于解决了..这是一个工作代码示例https://codesandbox.io/s/happy-framework-e27gl?file=/src/App.js
基本上我改了4个地方
将 更改为以下内容
{ Object.values(task).filter((c) => c.id == x.id).length > 0 ? Object.values(task).filter((c) => c.id == x.id).map(obj => <input id={x.id} type="text" name="task" placeholder="Write a task name" value={obj.value} onChange={e => handleChange(e, x)} />) : <input id={x.id} type="text" name="task" placeholder="I am duplicate" onChange={e => handleChange(e, x)} /> }
更改{任务|| “写一个任务名称……”到下面
<span>{ Object.values(task).filter((c) => c.id == x.id).length > 0 ? Object.values(task).filter((c) => c.id == x.id).map(obj => obj.value) : "I am the span" } </span>
这个问题花了我一整天的时间来排序,因为 jsx 没有指出正确的错误,我继续修复其他地方..它只是给我以下错误
Error: Objects are not valid as a React child (found: object with keys {id, value}).
P.S: 另外我在我的代码中用 obj 替换了 {id, value}
这个很直接
const [task, setTask] = useState([]);
这就是魔法! (虽然很麻烦)
const handleChange = (e, container) => { const { value, id } = e.currentTarget; const oldArray = Object.values(task); const pos = oldArray.map(function(e) { return e.id; }).indexOf(container.id); console.log('position: ' + pos); const matched = oldArray.filter(c => c.id === container.id); if(matched.length > 0){ oldArray[pos] = {"id": container.id, "value":value}; setTask(oldArray); console.log("hey") } else{ var newStateArray = oldArray.slice(); newStateArray.push({"id": container.id, "value":value}); setTask(newStateArray); console.log("comments added: " + value + " id: " + container.id); } }