Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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

I read the controlled and uncontrolled input from React page and follow what they recommend but somehow the warning about uncontrolled into controlled still there.

My code below is actually a page component to edit the data for the project detail. I set the values of the form to the project data after retrieve from 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;

I found that the code below is source of the warning, I did remove and the warning gone. I want to know what exactly my mistake that cause the warning and the solution for this.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

Here is sample of API retrieved,

    {
        "_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"
            }
        ],
    }

>Solution :

This is most likely happening because one of the properties of projects is undefined.

Try checking that each property is not undefined before setting it:

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]);

Or, you could use nullish coalescing:

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

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading