Reputation: 97
This is my edit-exercises component given below. So in my exercises component when I am clicking edit to update my exercises with respect to its id, it has to render to edit-exercise component but on rendering it gives above mentioned error. This is my component for the reference. In this, in useEffect I am fetching my exercise with given id from the URL.
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import axios from "axios";
const EditExercise = (props) => {
const [userDetails, setUserDetails] = useState({
username: "",
description: "",
duration: 0,
date: new Date(),
users: [],
});
useEffect(() => { //This is the getting from backend
axios
.get("http://localhost:5000/exercises/"+props.match.params.id)
.then(res => {
setUserDetails({
username: res.data.username,
description: res.data.description,
duration: res.data.duration,
date: new Date(res.data.date),
})
})
.catch((err) => {
console.log(err);
});
axios
.get("http://localhost:5000/users/")
.then((res) => {
if (res.data.length > 0) {
setUserDetails({
users: res.data.map((user) => user.username),
});
}
})
.catch((err) => {
console.log(err);
});
},[props.match.params.id]);
const changeUsernameHandler = (e) => {
setUserDetails((prevState) => {
return {
...prevState,
username: e.target.value,
};
});
};
const changeDescriptionHandler = (e) => {
setUserDetails((prevState) => {
return {
...prevState,
description: e.target.value,
};
});
};
const changeDurationHandler = (e) => {
setUserDetails((prevState) => {
return {
...prevState,
duration: e.target.value,
};
});
};
const changeDateHandler = (date) => {
setUserDetails((prevState) => {
return {
...prevState,
date: date,
};
});
};
const onSubmitHandler = (e) => { //On submit this code will run
e.preventDefault();
const exercise = {
username: userDetails.username,
description: userDetails.description,
duration: userDetails.duration,
date: userDetails.date,
};
console.log(exercise);
axios
.post("http://localhost:5000/exercises/update/"+props.match.params.id, exercise)
.then((res) => console.log(res.data));
window.location = "/";
};
return (
<div>
<h3>Edit Exercise log</h3>
<form onSubmit={onSubmitHandler}>
<div className="form-group">
<label>Username: </label>
<select
required
className="form-control"
onChange={changeUsernameHandler}
value={userDetails.username}
>
{userDetails.users.map((user) => {
return (
<option key={user} value={user}>
{user}
</option>
);
})}
</select>
</div>
<div className="form-group">
<label>Description: </label>
<input
type="text"
required
className="form-control"
onChange={changeDescriptionHandler}
value={userDetails.description}
/>
</div>
<div className="form-group">
<label>Duration (in minutes): </label>
<input
type="number"
className="form-control"
onChange={changeDurationHandler}
value={userDetails.duration}
/>
</div>
<div className="form-group">
<label>Date: </label>
<div>
<DatePicker
onChange={changeDateHandler}
selected={userDetails.date}
/>
</div>
</div>
<div>
<input
type="submit"
value="Edit Exercise Log"
className="btn btn-primary"
/>
</div>
</form>
</div>
);
};
export default EditExercise;```
>Please suggest what can be done to render the edit-exercise component
Upvotes: 0
Views: 88
Reputation: 509
Cannot read property 'map' of undefined
This error is thrown because the array you are trying to map doesn't exist. Please check if the array exists before you map the array. users: res.data ? res.data.map((user) => user.username) : [], And
{userDetails.users && userDetails.users.map((user) => {
return (
<option key={user} value={user}>
{user}
</option>
);
})}
Since axios.get
returns a promise, and setUserDetails
is set after the promise is returned, you need to be careful on when useEffect
is triggered. Currently useEffect
is triggered when props.match.params.id
is changed.
There are 2 possible solutions for it:
Either, you can remove props.match.params.id
from the useEffect
second parameter.
Or you can this section outside the useEffect hook:
axios
.get("http://localhost:5000/users/")
.then((res) => {
if (res.data.length > 0) {
setUserDetails({
users: res.data.map((user) => user.username),
});
}
})
.catch((err) => {
console.log(err);
});
Upvotes: 1