State gets updated but doesnt reflect some particular changes in my photo feed react app UI

Brief intro:
Hey guys i am into learning react.I have made a couple of apps using react like hotel website(using react & contentful cms), e-commerce website(using react, contentful cms, paypal), githubfinder app, todos app, live streaming app.

Right now i making a photofeed app kindda like instagram where a user can upload pictures. I am making this app using react and firebase..Also i am using firebase authentication for it.. so basically what is happening is when a new user signs up he goes to his profile and updates his details in updateProfile component..he can have a display name, a bio, a website link, a profile pic. Once he updates all his details he is sent back to his profile page wherein his name email profile pic etc are displayed…

PROBLEM(ISSUE):
The problem i am facing is when i for example want to add a profile pic, i click on change icon select the pic and then click on update icon..
Two things(functions ) happen:
1)On image input change: a function named handleProfilePic in invoked, in this func i am uploading the pic to a firebase storage collection, named ‘user_dps’, getting the url download link , and storing the download link in state variable named url..(setUrl(the url link i got from firebase storage)

2)On update button click: a function is invoked which creates a user document in firestore, named users and adds the field, profilePic and sets its value to the url i earlier got from firebase storage.

Everything is fine upto this point.But in the update click function i am sending the user to his profile page using history.push(‘/profilepage’). Once the userProfile component mounts i run a function, getUrl, inside useEffect, which basically gets the user document from firestore, storing them in the state and display the different details of the user in the ui. This is where my problem occurs, i am unable to see the updated profile pic, i am still seeing the old pic although the details i am getting from firestore reflect the updated values.
I have to click on the refresh button in my browser then and only then the app displays the new picture…??
If i am storing the user document details in my state after getting them, means the component should re render and update the ui automatically, why am i not able to see the changes?

Thanks for reading.

My code:

//userprofile component

import React, {
  useState,
  useEffect
} from 'react';
import styled from 'styled-components';
import StickyBar from './StickyBar';
import {
  BsFillGearFill
} from 'react-icons/bs';
import {
  Link
} from 'react-router-dom';
import {
  projectFirestore
} from '../firebase/config';
import {
  auth
} from '../firebase/config';

const ProfilePage = () => {
  const [profilePic, setProfilePic] = useState();
  const [website, setWebsite] = useState();
  const [bio, setBio] = useState();
  const [displayName, setDisplayName] = useState();
  const [email, setEmail] = useState();

  useEffect(() => {
    let isSubscribed = true;
    async function getUrl() {
      try {
        if (isSubscribed) {
          var user = auth.currentUser;
          var uid = user.uid;
          if (user) {
            try {
              const userDocument = await projectFirestore
                .doc(`users/${uid}`)
                .get()
                .then(async doc => {
                  const data = await doc.data();

                  const {
                    website,
                    email,
                    displayName,
                    profilePic,
                    bio
                  } = data;
                  if (website) {
                    setWebsite(website);
                  }
                  if (email) {
                    setEmail(email);
                  }
                  if (displayName) {
                    setDisplayName(displayName);
                  }
                  if (bio) {
                    setBio(bio);
                  }

                  setProfilePic(profilePic);

                  console.log(profilePic);
                });
              return userDocument;
            } catch (error) {
              console.error('Error fetching user', error);
            }
          }
        }
      } catch {
        if (isSubscribed) {
          console.log('failed to get the file');
        }
      }
    }
    getUrl();

    return () => (isSubscribed = false);
  }, [profilePic]);

  return ( <
    ProfileWrapper >
    <
    div className = 'profile' > {
      ' '
    }
    Firegram {
      ' '
    } <
    div className = 'icon-gear' > {
      ' '
    } <
    Link to = '/updateprofile' > {
      ' '
    } <
    BsFillGearFill / >
    <
    /Link> <
    /div> <
    /div> <
    div className = 'grid' >
    <
    div className = 'img-container' >
    <
    img src = {
      profilePic
    }
    alt = '' / >
    <
    /div> <
    div className = 'username' > {
      ' '
    } <
    strong > {
      displayName
    } < /strong> <
    /div> <
    div className = 'follow-stuff' >
    <
    p > {
      ' '
    } <
    strong > 8 < /strong> posts <
    /p> <
    p > {
      ' '
    } <
    strong > 24 k < /strong> Followers <
    /p> <
    p > {
      ' '
    } <
    strong > 120 < /strong> Following <
    /p> <
    /div> <
    div className = 'about' >
    <
    strong > Bio: < /strong>

    {
      bio
    } <
    /div> <
    div className = 'email' >
    <
    strong > Email: < /strong> {
      email
    } <
    /div> <
    div className = 'website' >
    <
    strong > Website: < /strong> {
      website
    } <
    /div> <
    /div> <
    StickyBar / >
    <
    /ProfileWrapper>
  );
};

export default ProfilePage;

const ProfileWrapper = styled.div `
    width: 100%;
    height: 100%;

    // .btn-logout {
    //  padding: 1rem;
    //  background: rgba(40, 200, 255, 0.7);
    //  border: 0;
    // }
    .profile {
        font-family: 'Billabong';
        font-size: 2rem;
        text-align: center;
        padding: 0.5rem;
        margin: 0;
        width: 100%;
        position: relative;
    }
    .grid {
        display: grid;
        grid-template-columns: repeat(3, 100px);
        grid-template-rows: repeat(7, 40px);
        grid-column-gap: 0.5rem;
        justify-content: flex-start;
        align-items: flex-start;
        padding: 0.5rem;
        background: rgba(248, 248, 248, 0.7);
        border: 1px solid #ececec;
    }

    .img-container {
        width: 100%;
        height: 100%;
        padding: 1rem 0.1rem;
    }
    .img-container > img {
        border-radius: 50%;
        height: 90px;
        width: 90px;
        border: 1px solid #ececec;
    }
    .follow-stuff {
        display: inline-flex;
        grid-column: 2/4;
        font-size: 0.7rem;
        text-align: left;
        grid-row: 3/4;
    }
    .follow-stuff p {
        text-align: center;
        margin: 0 0.5rem;
        margin-left: 0;
    }
    .about {
        grid-column: 1/4;
        padding: 0.5rem 0;
        font-size: 0.9rem;
        font-family: 'Open Sans';
        grid-row: 4/6;
    }
    .username {
        padding-top: 20%;
        grid-column: 2/4;
    }
    .icon-gear {
        position: absolute;
        right: 5px;
        top: 13px;
        font-size: 1.5rem;
        cursor: pointer;
    }
    .icon-gear a {
        color: black;
    }
    .email {
        grid-row: 5/6;
        grid-column: 1/4;
    }
    .website {
        grid-row: 6/7;
        grid-column: 1/4;
    }
`;
//`enter code here`update profile pic
import React, {
  useRef,
  useState
} from 'react';
import {
  IoIosAddCircle
} from 'react-icons/io';
import {
  AiFillFire
} from 'react-icons/ai';
import {
  useAuth
} from '../context/AuthProvider';
import {
  projectFirestore,
  projectStorage
} from '../firebase/config';
import StickyBar from './StickyBar';
import styled from 'styled-components';
import {
  useHistory
} from 'react-router-dom';

const UpdateProfile = () => {
  const history = useHistory();
  const usernameRef = useRef();
  const picRef = useRef();
  const bioRef = useRef();
  const websiteRef = useRef();
  const changeEmailRef = useRef();
  const [displayName, setDisplayName] = useState('');
  const [bio, setBio] = useState('');
  const [website, setWebsite] = useState('');
  const [url, setUrl] = useState('');

  const [error, setError] = useState('');
  const [updating, setUpdate] = useState(false);
  const {
    logOut,
    currentUser
  } = useAuth();
  // on change handler
  function onChangeHandler() {
    if (usernameRef.current.value) {
      setDisplayName(usernameRef.current.value);
    }

    if (bioRef.current.value) {
      setBio(bioRef.current.value);
    }

    if (websiteRef.current.value) {
      setWebsite(websiteRef.current.value);
    }
  }
  // handle profile pic
  function handleProfilePic(e, uid) {
    e.preventDefault();

    try {
      setUpdate(true);
      var storageRef = projectStorage.ref();
      var userRef = storageRef.child('users_dp');
      var imageRef = userRef.child(`${uid}/profile_pic.jpg`);
      imageRef.put(e.target.files[0]).then(async snap => {
        let percentage = (snap.bytesTransferred / snap.totalBytes) * 100;
        console.log(percentage);
        const url = await imageRef.getDownloadURL();
        setUpdate(false);
        setUrl(url);
        generateUserDocument(currentUser);
      });
    } catch {
      setError('Error, couldnt change profile pic.');
      alert(error);
    }
  }
  // handle the update

  function handleUpdate() {
    if (displayName) {
      currentUser
        .updateProfile({
          displayName: displayName,
        })
        .then(() => console.log('update username'))
        .catch(error => console.log(error));
    }

    generateUserDocument(currentUser);
  }

  const generateUserDocument = async user => {
    if (!user) return;
    const userRef = projectFirestore.doc(`users/${user.uid}`);
    const snapshot = await userRef.get();
    const {
      email
    } = user;

    if (!snapshot.exists) {
      try {
        await userRef.set({
          email: email,
          displayName: displayName,
          website: website,
          bio: bio,
          profilePic: url,
        });
        console.log('brand new document generated');
      } catch (error) {
        console.log('couldnt generate document', error);
      }
    } else if (snapshot.exists) {
      try {
        console.log(url);
        if (url) {
          await userRef.update({
            profilePic: url,
          });
        }
        if (displayName) {
          await userRef.update({
            displayName: displayName,
          });
        }
        if (email) {
          await userRef.update({
            email: email,
          });
        }

        if (bio) {
          await userRef.update({
            bio: bio,
          });
        }
        if (website) {
          await userRef.update({
            website: website,
          });
        }

        console.log('document updated');
      } catch (error) {
        console.log('Error updating user document', error);
      }
    }
    history.push('/profilepage');
    return getUserDocument(user.uid);
  };
  //   get user document
  const getUserDocument = async uid => {
    if (!uid) return null;
    try {
      const userDocument = await projectFirestore.doc(`users/${uid}`).get();
      return {
        uid,
        ...userDocument.data(),
      };
    } catch (error) {
      console.error('Error fetching user', error);
    }
  };
  // use effect
  if (updating) {
    return <div > Updating < /div>;
  } else if (!updating) {
    return ( <
      UpdateWrapper >
      <
      StickyBar / >
      <
      div className = 'header' >
      <
      AiFillFire / >
      <
      div className = 'firegram' > Firegram < /div> <
      /div> <
      div className = 'update-details' >
      <
      div >
      <
      label className = 'pic-icon' >
      <
      p > Update Profile Picture < /p> <
      div > {
        ' '
      } <
      IoIosAddCircle / >
      <
      /div> <
      input type = 'file'
      id = 'img'
      name = 'img'
      accept = 'image/*'
      ref = {
        picRef
      }
      onChange = {
        e => handleProfilePic(e, currentUser.uid)
      }
      /> <
      /label> <
      /div>

      <
      div className = 'form-control' >
      <
      label htmlFor = 'username' > Username: < /label> <
      input type = 'text'
      placeholder = 'username'
      name = 'username'
      id = 'username'
      ref = {
        usernameRef
      }
      onChange = {
        onChangeHandler
      }
      /> <
      /div> <
      div className = 'form-control' >
      <
      label htmlFor = 'bio' > Add bio: < /label>

      <
      input type = 'text'
      placeholder = 'bio'
      name = 'bio'
      id = 'bio'
      ref = {
        bioRef
      }
      onChange = {
        onChangeHandler
      }
      /> <
      /div> <
      div className = 'form-control' >
      <
      label htmlFor = 'website' > Website: < /label> <
      input type = 'text'
      placeholder = 'website'
      name = 'website'
      id = 'website'
      ref = {
        websiteRef
      }
      onChange = {
        onChangeHandler
      }
      /> <
      /div> <
      div className = 'form-control' >
      <
      label htmlFor = 'changeEmail' > Email: < /label> <
      input type = 'text'
      placeholder = 'changeEmail'
      name = 'changeEmail'
      id = 'changeEmail'
      ref = {
        changeEmailRef
      }
      /> <
      /div> <
      div className = 'form-control ' >
      <
      a href = '/signin'
      className = 'log-out' >
      <
      button className = 'btn-logout'
      onClick = {
        logOut
      } >
      Logout <
      /button> <
      /a> <
      /div> <
      div className = 'form-control' >
      <
      button className = 'btn-update'
      onClick = {
        handleUpdate
      } >
      Update <
      /button> <
      /div> <
      /div> <
      /UpdateWrapper>
    );
  }
};

export default UpdateProfile;

const UpdateWrapper = styled.div `
    .header {
        width: 100%;
        display: inline-flex;
        padding: 1rem;
        border-bottom: 1px solid #ececec;
        font-size: 2rem;
        font-family: 'Billabong';
    }
    .firegram {
        margin-left: 1.5rem;
        padding: 0 1.5rem;
        border-left: 2px solid black;
        font-family: 'Billabong';
    }
    .update-details {
        display: grid;
        grid-template-columns: repeat(1, minmax(300px, 1fr));
        grid-row-gap: 0.8rem;
        margin: 1rem 0;
        padding: 0 0.5rem;
    }
    input {
        width: 70%;
        height: 30px;
        margin-left: 0.2rem;
        border-radius: 0;
        border: 1px solid #ececec;
        padding: 0.2rem;
    }
    .btn-logout,
    .btn-update {
        background: #73c2fb;
        padding: 0.4rem 0;
        border: 1px solid #ececec;
        width: 100%;
        color: #fff;
        margin: 0;
    }
    .btn-update {
        background: #1fcecb;
    }
    .log-out {
        margin: 0;
    }
`;

26 thoughts on “State gets updated but doesnt reflect some particular changes in my photo feed react app UI”

Leave a Comment