I suggest you use useReducer hook in cases your state is complicated.
hooks API
useReducer is usually preferable to useState when you have complex
state logic that involves multiple sub-values or when the next state
depends on the previous one.
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;
SampleTestCase.js:
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;