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>
{/* <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>
<input onChange={changeBPM} value={bpm}></input>
</label>
<p></p>
<label> <b>Name</b>
<input onChange={changeName} value={name}></input>
</label>
<p></p>
<button onClick={sayKayeda}>Current Kayeda</button>
<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>
<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;
[]when it mounts again.run build? How did you check it run on build?