skip to Main Content

I’m building a form that has a select component that is wrapped with an array from an API MySQL "get" call. The array contains 3 items; userID, firstName and lastName.

Upon making a selection, the value of the select input is set the the selected userID which is then sent back to the same API. I also have two disabled input fields directly below the select component that I would like to automatically populate with the firstName and lastName based on the option the user selects.

States used:

const [userID, setUserID] = useState("");
const [studentOption, setStudentOption] = useState([]);
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");

useEffect to set state of select component

useEffect(() => {
  const config = {
    headers: { "x-auth-token": token },
  };

  const fetchData = async () => {
    const results = await api.get("/students/userID", config);
    setStudentOption(results.data);
  };

  fetchData();
}, [setStudentOption, token]);

Select Component:

<select
  className="form-select"
  aria-label="Default select example"
  onChange={(e) => setUserID(e.target.value)}
>
  <option>Select Student User Account</option>
  {studentOption.map((studentOption) => (
    <option key={studentOption.userID} value={studentOption.userID}>
      {studentOption.firstName} {studentOption.lastName}
    </option>
  ))}
</select>

The 2 input fields

<div className="row">
  <div className="col-md-6">
    <input
      disabled
      type="text"
      className="form-control"
      placeholder="Student First Name"
      onChange={(e) => setFirstName(e.target.value)}
      value={firstName}
    />
  </div>
  <div className="col-md-6">
    <input
      disabled
      type="text"
      className="form-control"
      placeholder="Student Last Name"
      onChange={(e) => setLastName(e.target.value)}
      value={lastName}
    />
  </div>
</div>

API controller for the get query

export const studentID = (req, res) => {
  db.query(
    "SELECT userID, firstName, lastName  FROM userIndex WHERE role = 'student' ORDER BY firstName ASC;",
    (err, rows) => {
      if (!err) {
        res.send(rows);
      } else {
        console.log(err).res.send({ alert: err });
      }
    }
  );
};

I can’t quite figure out the correct state changes for this one. I would appreciate any help! Let me know if I can supply any more code – thanks in advance.

2

Answers


  1. Chosen as BEST ANSWER

    Found a solution to the issue.

    In the select component, I left everything as above. All it does is set the userID state.

    Then I implemented a useEffect hook with an if statement to call the API for the firstName and lastName values and set them in the state, using the userID state value as a dependency. If userID is null, the useEffect doesn't run and vice versa.

    Select Component

    <select
      className="form-select"
      aria-label="Default select example"
      onChange={(e) => setUserID(e.target.value)}
    >
      <option>Select Student User Account</option>
      {studentOption.map((studentOption) => (
        <option key={studentOption.userID} value={studentOption.userID}>
          {studentOption.firstName} {studentOption.lastName}
        </option>
      ))}
    </select>;
    

    useEffect hook

    useEffect(() => {
        const config = {
          headers: { "x-auth-token": token },
        };
    
        const fetchData = async () => {
          const results = await api.get("/students/studentadd/" + userID, config);
          setFirstName(results.data[0].firstName);
          setLastName(results.data[0].lastName);
        };
        if (userID) {
          fetchData();
        }
      }, [userID, token]);
    

    I hope this helps anyone struggling with the same issue. Note this could does invoke another API call, so server usage could be impacted.

    If anyone has a more elegant solution, I'm all ears.


  2. I suppose the studentOptions array looks something like this.
    [{‘id’:’12’,’fname’:’anu’,’lname’:’sr’},{‘id’:’123′,’fname’:’surya’,’lname’:’r’}]
    Then you can try like below.

    <select
      className="form-select"
      aria-label="Default select example"
      onChange={(e) => {
        setUserID(e.target.value)
        setFirstName(studentOption.filter((s)=>s.id===e.target.id)[0].fname)
        setLastName(studentOption.filter((s)=>s.id===e.target.id)[0].fname)
        }}
    >
    

    Note this will change the first name and last name everytime when the select is changed by user.

    Let me know if the studentOption has a different structure or if you can share a codesandbox we can check for optimal solution.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search