Javascript 更新及;附加到React数组状态
我有一个表单,其中用户创建了一个编码问题。在表单中,可以通过输入和输出文本框添加示例测试用例。用户可以单击按钮添加新的测试用例。现在我有一个state对象,它保存所有表单数据formObj,其中有一个示例_test_cases字段,我想保存一个对象数组,比如:[{input:,output::}] 我遇到的问题是更新此阵列。我需要能够在每次添加测试用例时将一个新对象连接到它。然后在文本框更改时更新该索引处的状态。我尝试创建一个无状态数组并对其进行更新,然后将sample\u test\u案例设置到该数组中。然而,这是行不通的 这是一个包含我的代码的沙盒: 如果有人能给我一些有用的建议。我不太熟悉Javascript或复杂的状态管理。谢谢。请参阅下面的片段(我在保存沙箱时遇到问题)。它解决的几个问题:Javascript 更新及;附加到React数组状态,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我有一个表单,其中用户创建了一个编码问题。在表单中,可以通过输入和输出文本框添加示例测试用例。用户可以单击按钮添加新的测试用例。现在我有一个state对象,它保存所有表单数据formObj,其中有一个示例_test_cases字段,我想保存一个对象数组,比如:[{input:,output::}] 我遇到的问题是更新此阵列。我需要能够在每次添加测试用例时将一个新对象连接到它。然后在文本框更改时更新该索引处的状态。我尝试创建一个无状态数组并对其进行更新,然后将sample\u test\u案例设置
arr
变量跟踪状态;更新不会触发重新渲染,因此您需要修改formObj
状态中的sample\u test\u cases
数组值
也应该反映您的状态。为了方便起见,我将测试用例作为道具传递到SampleTestCase
组件中,因此它将对状态更改做出反应sample\u test\u cases
数组将状态设置为一个新对象,该数组由第一个i-1测试用例、一个修改了输入的新的第i个测试用例和剩余的测试用例构成SampleTestCase
移到AddProblemForm
组件之外。如果你不这样做,你会发现每当输入文本区域被改变时,你就会失去键盘的焦点。这是因为将在每个渲染上重新定义SampleTestCase
组件,该组件由状态更改触发。(类似问题:)import React,{useState}来自“React”;
从“react bootstrap”导入{Form,Button,Col};
从“反应图标/B”导入{BsPlusSquare};
const SampleTestCase=({testCase,updateInput})=>{
返回(
样本输入
样本输出
//setFormObj({
//…formObj,
//样本测试案例:{
//…形成样本测试案例,
//输出:event.target.value
// }
// })
// }
/>
);
};
const AddProblemForm=()=>{
const[formObj,setFormObj]=useState({
示例测试用例:[{input:,output:}]
//其他州obj信息
});
const AddSampleTestCase=()=>{
//创造新的实例!
const newTestCase={input:,output::};
setFormObj({
…formObj,
样本测试案例:[formObj.sample\u test\u cases,newTestCase]
});
};
控制台日志(formObj);
const updateInputFor=(i)=>(事件)=>{
event.preventDefault();
常数{sample_test_cases}=formObj;
常量测试用例=样本测试用例[i];
testCase.input=event.target.value;
setFormObj({
…formObj,
样本测试案例:[
…样本测试案例。切片(0,i),
测试用例,
…样本测试案例。切片(i+1)
]
});
};
返回(
问题表格
样本测试用例
{formObj.sample\u test\u cases.map((testCase,i)=>(
))}
添加示例测试用例
);
};
导出默认AddProblemForm;
我建议您在状态复杂的情况下使用useReducer钩子
当您遇到复杂的问题时,useReducer通常比useState更可取
涉及多个子值的状态逻辑,或当下一个状态
取决于前一个
AddProblemForm.js:
import React, { useReducer } from "react";
import { Form, Button, Col } from "react-bootstrap";
import { BsPlusSquare } from "react-icons/bs";
import SampleTestCase from "./SampleTestCase";
const initialState = {
sample_test_cases: [],
counter: 0
// other state obj info
};
function reducer(state, action) {
switch (action.type) {
case "addSampleTestCase": {
const { data } = action;
return {
...state,
sample_test_cases: [...state.sample_test_cases, data],
counter: state.counter + 1
};
}
case "updateTest": {
const { index, value } = action;
return {
...state,
sample_test_cases: state.sample_test_cases.map((item, i) => {
if (i === index) {
return value;
} else {
return item;
}
})
};
}
default:
throw new Error();
}
}
const AddProblemForm = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const AddSampleTestCase = () => {
dispatch({ type: "addSampleTestCase", data: { input: "", output: "" } });
};
/* console.log(state); */
return (
<div>
Problem Form
<Form>
<h5 style={{ paddingTop: "1rem" }}>Sample Test Cases</h5>
{state.sample_test_cases.map((sample_test_case, i) => (
<div key={i}>
<SampleTestCase
sample_test_case={sample_test_case}
updateValue={(value) =>
dispatch({ type: "updateTest", index: i, value })
}
/>
<hr />
</div>
))}
<Button onClick={AddSampleTestCase}>
<div>Add Sample Test Case</div>
</Button>
</Form>
</div>
);
};
export default AddProblemForm;
import React from "react";
import { Form, Button, Col } from "react-bootstrap";
const SampleTestCase = ({ sample_test_case, updateValue }) => {
return (
<Form.Row>
<Col>
<Form.Group controlId="input">
<Form.Label>Sample Input</Form.Label>
<Form.Control
required
as="textarea"
rows={2}
value={sample_test_case.input}
onChange={(event) => updateValue(event.target.value)}
/>
</Form.Group>
</Col>
<Col>
<Form.Group controlId="output">
<Form.Label>Sample Output</Form.Label>
<Form.Control
required
as="textarea"
rows={2}
value={sample_test_case.output}
onChange={(event) => updateValue(event.target.value)}
/>
</Form.Group>
</Col>
</Form.Row>
);
};
export default SampleTestCase;
import React,{useReducer}来自“React”;
从“react bootstrap”导入{Form,Button,Col};
从“反应图标/B”导入{BsPlusSquare};
从“/SampleTestCase”导入SampleTestCase;
常量初始状态={
样本测试案例:[],
柜台:0
//其他州obj信息
};
功能减速机(状态、动作){
开关(动作类型){
案例“addSampleTestCase”:{
const{data}=动作;
返回{
……国家,
样本测试案例:[状态.样本测试案例,数据],
计数器:state.counter+1
};
}
案例“updateTest”:{
常量{index,value}=action;
返回{
……国家,
示例测试用例:state.sample\u test\u cases.map((项目,i)=>{
如果(i==索引){
返回值;
}否则{
退货项目;
}
})
};
}
违约:
抛出新错误();
}
}
const AddProblemForm=()=>{
const[state,dispatch]=useReducer(reducer,initialState);
const AddSampleTestCase=()=>{
分派({type:“addSampleTestCase”,数据:{input:,output::}});
};
/*console.log(状态)*/
返回(
问题表格
样本测试用例
{state.sample\u test\u cases.map((sample\u test\u case,i)=>(
分派({type:“updateTest”,索引:i,value})
}
/>
))}
添加示例测试用例
);
};
导出默认AddProblemForm;
SampleTestCase.js:
import React, { useReducer } from "react";
import { Form, Button, Col } from "react-bootstrap";
import { BsPlusSquare } from "react-icons/bs";
import SampleTestCase from "./SampleTestCase";
const initialState = {
sample_test_cases: [],
counter: 0
// other state obj info
};
function reducer(state, action) {
switch (action.type) {
case "addSampleTestCase": {
const { data } = action;
return {
...state,
sample_test_cases: [...state.sample_test_cases, data],
counter: state.counter + 1
};
}
case "updateTest": {
const { index, value } = action;
return {
...state,
sample_test_cases: state.sample_test_cases.map((item, i) => {
if (i === index) {
return value;
} else {
return item;
}
})
};
}
default:
throw new Error();
}
}
const AddProblemForm = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const AddSampleTestCase = () => {
dispatch({ type: "addSampleTestCase", data: { input: "", output: "" } });
};
/* console.log(state); */
return (
<div>
Problem Form
<Form>
<h5 style={{ paddingTop: "1rem" }}>Sample Test Cases</h5>
{state.sample_test_cases.map((sample_test_case, i) => (
<div key={i}>
<SampleTestCase
sample_test_case={sample_test_case}
updateValue={(value) =>
dispatch({ type: "updateTest", index: i, value })
}
/>
<hr />
</div>
))}
<Button onClick={AddSampleTestCase}>
<div>Add Sample Test Case</div>
</Button>
</Form>
</div>
);
};
export default AddProblemForm;
import React from "react";
import { Form, Button, Col } from "react-bootstrap";
const SampleTestCase = ({ sample_test_case, updateValue }) => {
return (
<Form.Row>
<Col>
<Form.Group controlId="input">
<Form.Label>Sample Input</Form.Label>
<Form.Control
required
as="textarea"
rows={2}
value={sample_test_case.input}
onChange={(event) => updateValue(event.target.value)}
/>
</Form.Group>
</Col>
<Col>
<Form.Group controlId="output">
<Form.Label>Sample Output</Form.Label>
<Form.Control
required
as="textarea"
rows={2}
value={sample_test_case.output}
onChange={(event) => updateValue(event.target.value)}
/>
</Form.Group>
</Col>
</Form.Row>
);
};
export default SampleTestCase;
从“React”导入React;
从“react bootstrap”导入{Form,Button,Col};
const SampleTestCase=({sample\u test\u case,updateValue})=>{
返回(
样本输入