0

I am building a profile page but i have some problems with storing the profile image to browser local storage. I choose the file from my device and upload it. but when i refresh the page, it s gone.

below is my code below and also a visual of the page. the local storage function works for everything in the page except for the image. what is the problem here ? If you can help i will be so glad.

enter image description here

useLocalStorage.js

import React from "react"
import { useState, useEffect } from "react";

function getStorageValue(key, defaultValue) {
  // getting stored value
  const saved = localStorage.getItem(key);
  const initial = JSON.parse(saved);
  return initial || defaultValue;
}

export const useLocalStorage = (key, defaultValue) => {
  const [value, setValue] = useState(() => {
    return getStorageValue(key, defaultValue);
  });

  useEffect(() => {
    // storing input name
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue];
};
formikData.js

import * as Yup from "yup";
const initialValues = {
  fullname: "",
  email: "",
  phone: "",
  bio: "",
  city: "",
  state: "",
  street: "",
  zip: "",
};

const yupValidation = {
  phone: Yup.number().required("Phone is Required"),
  bio: Yup.string().required("Bio is Required"),
  city: Yup.string().required("City is Required"),
  state: Yup.string().required("State is Required"),
  street: Yup.string().required("Street is Required"),
};

export { initialValues, yupValidation };
PersonalDetails.js

import React, { useState, useEffect } from "react";
import { Col, Row, Container, Alert } from "react-bootstrap";
import poodle from "../../images/poodle.jpg";
import { Formik, Field, Form, ErrorMessage } from "formik";
import { initialValues, yupValidation } from "./formikData";
import * as Yup from "yup";
import cities from "../../data/cities";
import "./PersonalDetails.css";
import { useSelector } from "react-redux";
import { db } from "../../firebase";
import { useLocalStorage } from "./useLocalStorage";
import { useTranslation } from "react-i18next";

const PersonalDetails = () => {
  const user = useSelector((state) => state.user);
  const [fullname, setFullname] = useLocalStorage("fullname", "");
  const [email, setEmail] = useLocalStorage("email", "");
  const [bio, setBio] = useLocalStorage("bio", "")
  const [phone, setPhone] = useLocalStorage("phone", "");
  const [city, setCity] = useLocalStorage("city", "");
  const [state, setState] = useLocalStorage("state", "");
  const [street, setStreet] = useLocalStorage("street", "");
  const [zip, setZip] = useLocalStorage("zip", "");
  const [alertShown, isAlertShown] = useState(false);
  const [picture, setPicture] = useLocalStorage("picture", poodle);
 
  const onChangePicture = e => {
    setPicture(URL.createObjectURL(e.target.files[0]));
  };

  const clearInfo = () => {
    setBio("")
    setPhone("")
    setCity("")
    setState("")
    setStreet("")
    setZip("")
    setPicture("");
  }

  const fetchUserName = async () => {
    try {
      const query = await db
        .collection("profile")
        .where("uid", "==", user.uid)
        .get();
      const data = await query.docs[0].data();
      setFullname(data.name);
      setEmail(data.email);
    } catch (err) {
      console.error(err);
      alert("An error occured while loading user data");
    }
  };

  useEffect(() => {
    if(user) fetchUserName();
  }, [user]);

  const { t } = useTranslation();

  return (
    <Container fluid className="mainContainer profile">
      <Container className="pt-3 pb-4">
        <Row>
          <Col lg="4" md="12">
            <div class="bgWhite fullHeight">
              <img
                src={picture}
                alt=""
                width="120"
                height="120"
                className="align-items-center mb-4 avatar"
              />
              <input className="mb-5" id="profilePic" type="file" onChange={onChangePicture} />
              <h5 className="mb-2 text-uppercase newColor">
                {fullname}
              </h5>
              <p className="newColor">
                {email}
              </p>
              <p className="profileInfo">
                Tel: {''}
                <span>{phone}</span>
              </p>
              <p className="profileInfo">
              {t("personalPage.sideText0")} : {''}
                <span>{city}</span>
              </p>
              <p className="profileInfo">
              {t("personalPage.sideText1")} : {''}
                <span>{state}</span>
              </p>
              <p className="profileInfo">
              {t("personalPage.sideText2")} : {''}
                <span>{street}</span>
              </p>
              <p className="profileInfo">
              {t("personalPage.sideText3")} : {''}
                <span>{zip}</span>
              </p>
              {bio && (
                <h4 className="mb-2 mt-4 newColor">About</h4>
              )}
              <p className="profileInfo">
                Bio: {''}
                <span>{bio}</span>
              </p>
            </div>
          </Col>
          <Col lg="8" md="12" className="mt-lg-0 mt-5 formSection">
            <div className="bgWhite personelInfo" align="left">
              {alertShown && (
                <Alert variant="success">{t("personalPage.alert0")}</Alert>
              )}
              <Formik
                initialValues={initialValues}
                validationSchema={Yup.object(yupValidation)}
                onSubmit={(values, { setSubmitting }) => {
                  isAlertShown(true);
                  setFullname(values.fullname)
                  setEmail(values.email);
                  setBio(values.bio)
                  setPhone(values.phone)
                  setCity(values.city)
                  setState(values.state)
                  setStreet(values.street)
                  setZip(values.zip)
                }}
              >
                {(props) => {
                  const { values } = props;
                  return (
                    <>
                      <Form>
                        <h3 className="newColor">{t("personalPage.title0")}</h3>
                        <div className="row d-flex justify-content-around mt-4">
                        </div>
                        <div className="row d-flex justify-content-around mt-4">
                          <div>
                            <Field
                              placeholder={t("personalPage.placeholder2")}
                              type="tel"
                              name="phone"
                              className="shadow inputStyle"
                            />
                            <div className="error">
                              <ErrorMessage name="phone" />
                            </div>
                          </div>
                          <div>
                            <Field
                              placeholder={t("personalPage.placeholder3")}
                              name="bio"
                              as="textarea"
                              className="shadow inputStyle"
                            />
                            <div className="error">
                              <ErrorMessage name="bio" />
                            </div>
                          </div>
                        </div>
                        <div className="mt-4">
                          <h3 className="newColor">{t("personalPage.title1")}</h3>
                          <div className="row d-flex justify-content-around mt-4 ">
                            <div>
                              <Field
                                component="select"
                                id="city"
                                name="city"
                                multiple={false}
                                className="shadow inputStyle"
                              >
                                <option value="">{t("personalPage.dropdown")}</option>
                                {cities.map((city) => {
                                  return (
                                    <option name="city">{city.name}</option>
                                  );
                                })}
                              </Field>
                              <div className="error">
                                <ErrorMessage name="city" />
                              </div>
                            </div>
                            <div>
                              <Field
                                placeholder={t("personalPage.placeholder5")}
                                type="text"
                                name="state"
                                className="shadow inputStyle"
                              />
                              <div className="error">
                                <ErrorMessage name="state" />
                              </div>
                            </div>
                          </div>
                          <div className="row d-flex justify-content-around mt-4 ">
                            <div>
                              <Field
                                placeholder={t("personalPage.placeholder6")}
                                type="text"
                                name="street"
                                className="shadow inputStyle"
                              />
                              <div className="error">
                                <ErrorMessage name="street" />
                              </div>
                            </div>
                            <div>
                              <Field
                                placeholder={t("personalPage.placeholder7")}
                                type="text"
                                name="zip"
                                className="shadow inputStyle"
                              />
                              <div className="error">
                                <ErrorMessage name="zip" />
                              </div>
                            </div>
                          </div>
                          <div className="row d-flex mt-5 justify-content-center">
                            <button
                              className="m-2 button"
                              type="submit"
                            >
                              {t("personalPage.button0")}{" "}
                            </button>
                            <button
                              className="m-2 button cancelBtn"
                              onClick={clearInfo}
                              type="button"
                            >
                              {t("personalPage.button1")}{" "}
                            </button>
                          </div>
                        </div>
                      </Form>
                    </>
                  );
                }}
              </Formik>
            </div>
          </Col>
        </Row>
      </Container>
    </Container>
  );
};

export default PersonalDetails;
skyboyer
  • 22,209
  • 7
  • 57
  • 64
Ayse8888
  • 137
  • 2
  • 16
  • I tried your code and image saved to local storage and got it back on page refresh. Your code worked just fine interestingly. I didn't use all of your code though. I just used your image and local storage custom hook. – Sanish Joseph Sep 06 '21 at 16:18
  • that is so weird. when i refresh the page, the image disappears :( – Ayse8888 Sep 06 '21 at 16:21
  • When you add an image, are you seeing the value getting stored in local storage? In developer tools, under Application, you can check. Also, add a debugger in your `getStorageValue` after commenting all other form values to narrow down the issue. You should have only the image upload now. Instead of a default image poodle, pass `null`. – Sanish Joseph Sep 06 '21 at 16:22
  • yeah, the weird thing is i see the picture in the local storage from the application. i cahnged to null. and the other weird thing is sometimes it works sometimes not. i really dont understand. how can i add a debugger ? – Ayse8888 Sep 06 '21 at 16:30
  • 1
    `debugger;` https://stackoverflow.com/questions/66420/how-do-you-launch-the-javascript-debugger-in-google-chrome#:~:text=Press%20the%20F12%20function%20key,debugger%20for%20the%20JavaScript%20code. – Sanish Joseph Sep 06 '21 at 16:32

0 Answers0