Reputation: 12009
While trying to edit
any of text fields throws error Cannot read property '0' of null
and the image also not updating to the database. Added a screen shot
TypeError: Cannot read property '0' of null handleChange
C:/Project/soccerpep/src/components/Profile.js:67
import React, {useEffect, useState } from "react";
import { useForm } from 'react-hook-form';
import { useHistory } from "react-router-dom";
import Axios from "axios";
const Profile = () => {
const [preview, setPreview] = useState('');
const [picture, setPicture] = useState('');
const [playerProfile, setPlayerProfile] = useState([]);
const loginUserEmail = localStorage.getItem('loginEmail');
const [updateProfile, setUpdateProfile] = useState({ _id: '', photo: '', name: '', email:'', phonenumber:'', position:'', privilege:'', password:''});
const [isSent, setIsSent] = useState(false);
const [helperText, setHelperText] = useState('');
const [disabled, setDisabled] = useState(true);
const { handleSubmit, register, errors } = useForm();
const history = useHistory();
const onChangePicture = e => {
console.log('picture: ', picture);
if (e.target.files.length) {
setPreview(URL.createObjectURL(e.target.files[0]));
setPicture({photo:e.target.files[0]});
} else {
return false;
}
};
// Pass the id to the handler so you will know which item id changing.
const handleChange = (e, id) => {
e.persist();
let itemIndex;
const targetPlayer = playerProfile.find((player, index) => {
console.log({ player, id, index });
itemIndex = index;
return player.id === id;
});
console.log({ targetPlayer, id, e });
const editedTarget = {
...targetPlayer,
[e.target.name]: e.target.value
};
const tempPlayers = Array.from(playerProfile);
tempPlayers[itemIndex] = editedTarget;
setPlayerProfile(tempPlayers);
setUpdateProfile({ ...updateProfile, [e.target.name]: e.target.value }); // this is added just to see if its working
setPicture({photo:e.target.files[0]});
};
useEffect(() => {
const fetchData = async () => {
try {
const params = {
email: loginUserEmail,
};
const res = await Axios.get('http://localhost:8000/service/profile', {params});
setPlayerProfile(res.data.playerProfile);
} catch (e) {
console.log(e);
}
}
fetchData();
}, []);
const onSubmit = () => {
setDisabled(disabled);
const formData = new FormData();
for(let key in updateProfile) {
formData.append(key,updateProfile[key]);
}
if (picture) formData.append("photo", picture);
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
const fetchData = async () => {
try {
const params = {
email: loginUserEmail,
};
const res = await Axios.put('http://localhost:8000/service/profile', formData, {params}, config);
console.log("Front End update message:" + res.data.success);
if (res.data.success) {
setIsSent(true);
history.push('/')
}
else {
console.log(res.data.message);
setHelperText(res.data.message);
}
} catch (e) {
setHelperText(e.response.data.message);
}
}
fetchData();
}
return (
<div className="register_wrapper">
<div className="register_player_column_layout_one">
<div className="register_player_Twocolumn_layout_two">
<form onSubmit={handleSubmit(onSubmit)} className="myForm" encType="multipart/form-data">
{
playerProfile.map(({ id, photo, name, email, phonenumber, position, privilege, password }) => (
<div key={id}>
<div className="formInstructionsDiv formElement">
<h2 className="formTitle">Profile</h2>
<div className="register_profile_image">
<input id="profilePic" name="photo" type="file" onChange={onChangePicture} />
</div>
<div className="previewProfilePic" >
<img alt="" onError={addDefaultSrc} name="previewImage" className="playerProfilePic_home_tile" src={photo} onChange={e => handleChange(e, id)}></img>
</div>
</div>
<div className="fillContentDiv formElement">
<label>
<input className="inputRequest formContentElement" name="phonenumber" type="text" value={phonenumber}
onChange={e => handleChange(e, id)}
maxLength={11}
ref={register({
required: "Phone number is required",
pattern: {
value: /^[0-9\b]+$/,
message: "Invalid phone number"
}
})}
/>
<span className="registerErrorTextFormat">{errors.phonenumber && errors.phonenumber.message}</span>
</label>
</div>
// rest of the form fields.....
<div className="submitButtonDiv formElement">
<button type="submit" className="submitButton">Save</button>
</div>
</div>
))
}
</form>
</div>
</div>
</div>
);
}
export default Profile;
Upvotes: 0
Views: 58
Reputation: 282120
handleChange
function is being used on input type="text"
which definitely doesn't return you files in target object and hence you see the error.
You are already using another event handler function for input type="file"
so you need not have any image handling in handleChange
. Also note that you don't need onChange on img
tag
const onChangePicture = e => {
if (e.target.files.length) {
setPreview(URL.createObjectURL(e.target.files[0]));
setUpdateProfile({ ...updateProfile, previewImage: e.target.files[0] });
setPicture({photo:e.target.files[0]});
} else {
return false;
}
};
// Pass the id to the handler so you will know which item id changing.
const handleChange = (e, id) => {
e.persist();
let itemIndex;
const targetPlayer = playerProfile.find((player, index) => {
console.log({ player, id, index });
itemIndex = index;
return player.id === id;
});
console.log({ targetPlayer, id, e });
const editedTarget = {
...targetPlayer,
[e.target.name]: e.target.value
};
const tempPlayers = Array.from(playerProfile);
tempPlayers[itemIndex] = editedTarget;
setPlayerProfile(tempPlayers);
setUpdateProfile({ ...updateProfile, [e.target.name]: e.target.value }); // this is added just to see if its working
// setPicture({photo:e.target.files[0]}); This isn't needed here
};
Upvotes: 1