如何在react中按状态更新输入值

问题描述 投票:0回答:1

我试图在用户键入时动态更新文本输入值(该值从 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;
reactjs react-hooks
1个回答
0
投票

如果您有一系列问题,请尝试这种方式

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}
/>

请告诉我这是否有帮助。我在我的一个项目中实施了相同的方法,其中我使用了一系列问题。虽然你的实现不同,但我尝试使用与我的项目中使用的相同的想法。

© www.soinside.com 2019 - 2024. All rights reserved.