反应输入,我将状态定义为初始状态但仍然收到警告将不受控制的输入更改为受控输入

React input, I defined the state into initial state but still get warning changing uncontrolled to controlled input

我从 React 页面读取了受控和不受控的输入,并按照他们的建议进行操作,但不知何故,关于不受控变成受控的警告仍然存在。

我下面的代码实际上是一个页面组件,用于编辑项目详细信息的数据。从 API.

检索后,我将表单的值设置为项目数据
import { useState } from "react";
import { useDispatch } from "react-redux";
import {
  updateProject,
  deleteProject,
  getProjectById,
  reset,
} from "../../features/project/projectSlice";
import { useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
import { useEffect } from "react";
import { Button, Container, Form, Modal, Col, Spinner, Stack, ListGroup, Dropdown, Row } from "react-bootstrap"
import Member from "./Member";

import AddMember from "./AddMember";

function EditProject() {

  // Modal
  const [show, setShow] = useState(false);
  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);

  // Data State
  const { id } = useParams();
  const dispatch = useDispatch();
  const navigate = useNavigate();
  const { isLoading, isError, projects, isSuccess, message } = useSelector(
    (state) => state.project
  );
  const {user} = useSelector((state)=> state.auth)

  const [code, setCode] = useState("");
  const [title, setTitle] = useState("");
  const [desc, setDesc] = useState("");
  const [users, setUsers] = useState([]);

  useEffect(() => {
    dispatch(getProjectById(id));
    if (isError) {
      console.log(message);
    }

    return () => dispatch(reset());
  }, [isError, message, dispatch]);

  useEffect(() => {
    if (isSuccess && projects) {
      setCode(projects.code);
      setTitle(projects.title);
      setDesc(projects.desc);
      setUsers(projects.users);
    }
  }, [isSuccess,projects]);

  // Data Saving
  const onSubmit = (e) => {
    e.preventDefault();
    const projectData = {
      code,
      title,
      desc,
      users: users.map((user)=> ({...user, _user: user._user._id}))
    };

    const projectChanges = {
      projectId: id,
      projectData,
    };
    console.log(projectData)
    dispatch(updateProject(projectChanges));
    navigate("/projects");
  };


  if (isLoading) {
    return (
      <Container className="mt-5" style={{ justifyContent: "center", display: "flex" }}>
        <Spinner animation="border" />
      </Container>
    )
  }

  if(user._id !== projects.manager){
    return <h5>You do not have permission to edit this project</h5>
  }

  return (
    <>
      <Container fluid="md" className="mt-5">
        <Form onSubmit={onSubmit}>
          <Stack gap={3}>
            <Form.Group>
              <Form.Label>Code</Form.Label>
              <Form.Control type="text" placeholder="Enter project codename" value={code} onChange={(e) => setTitle(e.target.value)} />
              <Form.Text className="text-muted">Codename is a short form of the project that used widely</Form.Text>
            </Form.Group>
            <Form.Group>
              <Form.Label>Title</Form.Label>
              <Form.Control type="text" rows={5} placeholder="Enter project description" value={title} onChange={(e) => setTitle(e.target.value)} />
            </Form.Group>
            <Form.Group>
              <Form.Label>Description</Form.Label>
              <Form.Control as="textarea" rows={5} placeholder="Enter project description" value={desc} onChange={(e) => setDesc(e.target.value)} />
            </Form.Group>
            <Form.Group>
              <Row className="mb-2">
                <Col className="vertical-align"><Form.Label style={{ margin: "0" }}>Team Member</Form.Label></Col>
                <Col md="auto"><Button variant="primary" onClick={handleShow}>Add People</Button></Col>
              </Row>
              <ListGroup>
                {users && users.map((user,index) => <Member key={user._user._id}  user={user} setUser={setUsers} users={users} index={index} />)}
              </ListGroup>
            </Form.Group>
            <Row className="align-items-end">
              <Col className="d-flex justify-content-end gap-2">
                <Button variant="danger" className="px-3">Delete</Button>
                <Button type="submit" className="px-5">Submit</Button>
              </Col>
            </Row>
          </Stack>
        </Form>
      </Container>
      <AddMember show={show} onHide={handleClose} />
    </>
  );
}

export default EditProject;

我发现下面的代码是警告的来源,我删除了警告就消失了。我想知道我的错误到底是什么导致了这个警告以及解决方法。

useEffect(() => {
    if (isSuccess && projects) {
      setCode(projects.code);
      setTitle(projects.title);
      setDesc(projects.desc);
      setUsers(projects.users);
    }
  }, [isSuccess,projects]);

这是检索到的 API 样本,

    {
        "_id": "abc123",
        "code": "PROJ",
        "title": "Project",
        "desc": "Project detail.",
        "users": [
            {
                "_user": "1",
                "role": "UI/UX Designer",
                "status": "Active"
            },
            {
                "_user": "2",
                "role": "Software Engineer",
                "status": "Active"
            }
        ],
    }

这很可能发生,因为 projects 的属性之一是 undefined

在设置之前尝试检查每个 属性 是否未定义:

useEffect(() => {
  if (isSuccess && projects) {
    if (projects.code !== undefined) {
      setCode(projects.code);
    }
    if (projects.title !== undefined) {
      setTitle(projects.title);
    }
    if (projects.desc !== undefined) {
      setDesc(projects.desc);
    }
    if (projects.users !== undefined) {
      setUsers(projects.users);
    }
  }
}, [isSuccess, projects]);

或者,您可以使用无效合并:

useEffect(() => {
  if (isSuccess && projects) {
    setCode(projects.code ?? '');
    setTitle(projects.title ?? '');
    setDesc(projects.desc ?? '');
    setUsers(projects.users ?? []);
  }
}, [isSuccess, projects]);