我试图在用户键入时动态更新文本输入值(该值从 useEffect 中设置的状态加载为数据),但这给我带来了一些麻烦。该值似乎没有随状态更新。
我有一个名为“问题”的状态,其中包含我从后端获取的一系列不同问题。
这是从我的后端获取的数据的示例。
[
{
"uuid": "mS2ZeSSF3N3AomPAaSnnVE",
"question": "test questiong",
"question_type": "Multiple Choice",
"question_answers": "Strongly Disagree/Disagree/Neither Agree Nor Disagree/Agree/Strongly Agree",
"section": "9UCuJXiuyNL3fLMbkMtBcW"
},
{
"uuid": "Xb3xytncs2S6rQtUnAxvvY",
"question": "test question 2",
"question_type": "Text",
"question_answers": null,
"section": "9UCuJXiuyNL3fLMbkMtBcW"
}
]
此数据是问题状态的集合
我正在创建一个更新页面,因此正在根据问题状态填充文本输入
{questions.map((question, index) => (
<Form.Group key={index}>
<Form.Label htmlFor={"question" + (index + 1)}>
Question {index + 1}.
</Form.Label>
<Form.Control
id={"question" + (index + 1)}
type="text"
className="form-control questionName"
placeholder="Question..."
required={true}
name="name"
onChange={(e) => {
}}
value={questions[index].question}
/>
<br />
</Form.Group>
))}
输入全部按预期加载,输入值显示正确的数据(问题.问题)
但是,我正在努力寻找一种在用户键入时更新文本输入值的方法。最初我将其添加到 onChange 事件 =>
let x = questions
questions[index].question = e.target.value
setQuestions(x)
想法是复制问题状态,更新特定问题,然后将问题状态重新设置为新的更新副本。这似乎不起作用,并且输入值没有改变:/
很想知道我错过了什么。任何帮助将不胜感激
编辑*** 这是我的整个 jsx 文件
import React, { useContext, useState, useEffect, useCallback } from "react";
import { useParams, useNavigate } from "react-router-dom";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import AuthContext from "../../../context/AuthContext";
import LoadingSpinner from "../../../components/LoadingComponents/LoadingSpinner";
const EditQuestionnaire = () => {
// context
let { accessToken } = useContext(AuthContext);
// params
let { questionnaireUUID } = useParams();
//states
let [questionnaire, setQuestionnaire] = useState({ uuid: "", name: "" });
let [sections, setSections] = useState([]);
let [currentPage, setCurrentPage] = useState(0);
let [loading, setLoading] = useState(true);
// get questionnaire data api call
let getQuestionnaire = useCallback(async () => {
let response = await fetch(
`${
import.meta.env.VITE_APP_API_DOMAIN
}/api/questionnaire/${questionnaireUUID}/`,
{
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
);
let data = await response.json();
if (response.status === 200) {
setQuestionnaire({ uuid: data.uuid, name: data.name });
setSections(data.sections);
console.log(data);
}
});
useEffect(() => {
if (loading) {
getQuestionnaire();
setLoading(false);
}
}, [getQuestionnaire, loading]);
return loading ? (
<LoadingSpinner />
) : currentPage === 0 ? (
<div className="create-survey-wrapper">
<div className="content-section survey-create">
<Form>
<Form.Group>
<legend className="border-bottom mb-4">Edit Questionnaire</legend>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicEmail">
<Form.Label>Questionnaire Name*</Form.Label>
<Form.Control
type="text"
placeholder="Questionnaire Name"
required={true}
name="name"
onChange={(e) => {
setQuestionnaire({ ...questionnaire, name: e.target.value });
}}
value={questionnaire.name}
/>
</Form.Group>
<Button
variant="outline-primary"
onClick={() => {
setCurrentPage(currentPage + 1);
}}
>
Next
</Button>
</Form>
</div>
</div>
) : (
<div className="create-survey-wrapper">
<div className="content-section survey-create">
<Form>
<Form.Group>
<legend className="border-bottom mb-4">Edit Questionnaire</legend>
</Form.Group>
<Form.Group>
<legend className="border-bottom mb-4">
Section {currentPage}
</legend>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicSectionName">
<Form.Label>Section Name*</Form.Label>
<Form.Control
type="text"
placeholder="Section Name"
required={true}
name="name"
onChange={(e) => {}}
value={sections[currentPage - 1].name}
/>
</Form.Group>
<br />
<hr />
<Form.Group>
<legend className="border-bottom mb-4">Questions</legend>
</Form.Group>
{sections[currentPage - 1].questions.map((question, index) => (
<Form.Group key={index}>
<Form.Label htmlFor={"question" + (index + 1)}>
Question {index + 1}.
</Form.Label>
<Form.Control
id={"question" + (index + 1)}
type="text"
className="form-control questionName"
placeholder="Question..."
required={true}
name="name"
onChange={(e) => {
let x = sections;
x[currentPage - 1].questions[index].question = e.target.value;
console.log(x);
setSections(x);
}}
value={sections[currentPage - 1].questions[index].question}
/>
<br />
</Form.Group>
))}
<Button
variant="outline-primary"
onClick={() => {
setCurrentPage(currentPage - 1);
}}
>
Prev
</Button>{" "}
{currentPage < sections.length ? (
<Button
variant="outline-primary"
onClick={() => {
setCurrentPage(currentPage + 1);
}}
>
Next
</Button>
) : (
<Button variant="outline-primary">Save</Button>
)}
</Form>
</div>
</div>
);
};
export default EditQuestionnaire;
如果您有一系列问题,请尝试这种方式
const handleQuestionChange = (index, value) => {
const updatedSections = [...sections]; // create a copy of section first
const updatedQuestions = [...updatedSections[currentPage - 1].questions]; // copy all the questions as well from that section
updatedQuestions[index].question = value; // updating the value of that question on the given index
updatedSections[currentPage - 1].questions = updatedQuestions; updating that current section
setSections(updatedSections);
};
<Form.Control
id={"question" + (index + 1)}
type="text"
className="form-control questionName"
placeholder="Question..."
required={true}
name="name"
onChange={(e) => handleQuestionChange(index, e.target.value)}
value={sections[currentPage - 1].questions[index].question}
/>
请告诉我这是否有帮助。我在我的一个项目中实施了相同的方法,其中我使用了一系列问题。虽然你的实现不同,但我尝试使用与我的项目中使用的相同的想法。