soccerway
soccerway

Reputation: 12009

While trying to edit, system throws Cannot read property '0' of null

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 enter image description here

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

Answers (1)

Shubham Khatri
Shubham Khatri

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

Related Questions