How to persist state in react if local storage does not work

23 views Asked by At

For a react project that I am building, I have a context provider which gives the user a link to a composition based on the parameters they selected. I want this state(the compositions) to be saved, and have tried local storage, however my state is not persisting after a refresh.

Here is the code for my context provider

import {createContext, useContext, useState, useEffect} from 'react';
import { storage } from '../../../Config/firebaseConfig';
import {ref, deleteObject} from 'firebase/storage'

 const CompositionsContext = createContext(['There are no Compositions']);

 const useCompositions = () => useContext(CompositionsContext);

 const CompositionContextProvider = ({children}) => {
    const[compositions, setCompositions] = useState([]);

    useEffect(() => {
        const storedState = localStorage.getItem('compositions');
        if (storedState) {
          setCompositions(JSON.parse(storedState));
        }
      }, []);
    
      useEffect(() => {
        localStorage.setItem('compositions', JSON.stringify(compositions));
      }, [compositions]);

    const addNewComposition = (newComposition) => {
        setCompositions(compositions => compositions.concat(newComposition));
    }

    const deleteComposition = (indexValue) => {
        setCompositions(compositions => compositions.filter((_,index) => index !== indexValue))
        const storageRef = ref(storage, `pdfs/${compositions[indexValue ]}.pdf`)
        deleteObject(storageRef);
    }


    return (
        <CompositionsContext.Provider value={{addNewComposition, compositions, deleteComposition}}>
            {children}
        </CompositionsContext.Provider>
    )
 }

 export {useCompositions};
 export default CompositionContextProvider;

And here are the components in which the ContextProvider is being used.

import React, { useState } from 'react';
import { useCompositions } from './Contexts/CompositionContextProvider';


const CreateComposition = () =>{
    const {addNewComposition} = useCompositions();
    const [taal, setTaal] = useState('');
    const [bpm, setBpm] = useState('');
    const [name, setName] = useState('');

    const options = [
      {label : "", value: ""},
      {label: "Teentaal", value: "Teentaal"},
      {label: "Jhaptaal", value: "Jhaptaal"},
      {label: "Ektaal", value: "Ektaal"},
      {label: "Rupak", value: "Rupak"}
    ]
  
    const sayKayeda = () => {
      alert(taal + " " + bpm + " " + name);
    }
  
    const changeTaal = (event) => {
      setTaal(event.target.value);
    }
  
    const changeBPM = (event) => {
      setBpm(event.target.value);
    }
  
    const changeName = (event) => {
      setName(event.target.value);
    }

  
    const addNewCompositionHandler = () => {
      const newComposition = `${taal}_${bpm}_${name}`;
      addNewComposition(newComposition)
      setTaal('');
      setBpm('');
      setName('');
      
    }


    return (
    <>
        <h2>Input Kayeda Details Below</h2>
        <br></br>
        <br></br>
        <label> <b>Select a Taal</b>&nbsp; 
          {/* <input onChange={changeTaal} value={taal}></input> */}
          <select onChange = {changeTaal}>
            {options.map(option =>(
              <option value={option.value}>{option.label}</option>
            ))}
          </select>
        </label>
        <p></p>
        <label> <b>BPM</b>&nbsp; 
            <input onChange={changeBPM} value={bpm}></input>
        </label>
        <p></p>
        <label> <b>Name</b>&nbsp; 
            <input onChange={changeName} value={name}></input>
        </label>
        <p></p>
        <button onClick={sayKayeda}>Current Kayeda</button>
        &nbsp; 
        <button onClick={addNewCompositionHandler}>Add Composition</button>
        <p></p>
    </>
    );
}


export default CreateComposition;

Here is the second component

// Compositions.js
import React, { useEffect, useState } from 'react';
import { useCompositions } from './Contexts/CompositionContextProvider';
import TeentaalPDF from '../../PDFs/TeentaalE.pdf';
import JhaptaalPDF from '../../PDFs/JhaptaalE.pdf';
import EktaalPDF from '../../PDFs/EktaalE.pdf';
import RupakPDF from '../../PDFs/RupakE.pdf';
import { storage } from '../../Config/firebaseConfig';
import { ref, getDownloadURL, uploadBytes} from 'firebase/storage';

const Compositions = () => {
  const {compositions, deleteComposition} = useCompositions();
  const [pdfLinks, setPdfLinks] = useState({});
  const [fileUpload, setFileUpload] = useState(null);

  useEffect(() => {
    const fetchPDFLinks = async () => {
      const links = {};
      for (const composition of compositions) {
        const downloadURL = await getPDFDownloadURLFromStorage(composition);
        links[composition] = downloadURL || getDefaultPDF(composition);
      }
      setPdfLinks(links);
    };

    fetchPDFLinks();
  }, [compositions]);

  const getPDFDownloadURLFromStorage = async (composition) => {
    const storageRef = ref(storage, `pdfs/${composition}.pdf`);
    try {
      const downloadURL = await getDownloadURL(storageRef);
      return downloadURL;
    } catch (error) {
      console.error(error);
      return null
    }
  };

  const getDefaultPDF = (composition) => {
    if (composition.includes('Teentaal')) {
      return TeentaalPDF;
    } else if (composition.includes('Jhaptaal')) {
      return JhaptaalPDF;
    } else if (composition.includes('Ektaal')) {
      return EktaalPDF;
    } else if (composition.includes('Rupak')) {
      return RupakPDF;
    } else {
      return null; // Return null or a default PDF for unmatched compositions
    }
  };

  const onSubmitComposition = async (newCompositionName) => {
    if(!fileUpload) return;
    const storageRef = ref(storage, `pdfs/${newCompositionName}.pdf`);
    try {
      await uploadBytes(storageRef, fileUpload); // Uploading file to Firebase Storage

    } catch (error) {
      console.error('Error uploading file:', error);
    }
  };

  return (
    <>
      <h2>List of Compositions</h2>
      <h2>{compositions.length}</h2>
      <ul>
        {compositions.map((composition, index) => (
          <li key={index}>
            <a href={pdfLinks[composition]} target="_blank" rel="noreferrer">{composition} </a> &nbsp;
            <button onClick={() => deleteComposition(index)}>Delete Composition</button>
            <p>
              <input type = "file" onChange={(e) => setFileUpload(e.target.files[0])}/>
              <button onClick={() => onSubmitComposition(composition)}>
                Store Composition
              </button>
            </p>
          </li>
        ))}
      </ul>
    </>
  );
};

export default Compositions;
0

There are 0 answers