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.
CodePudding user response:
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.
CodePudding user response:
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.