I'm working on overhauling the state manage of an application I'm working on, and attempting to set it up with a context provider. I only have limited number of states to track, and it's a relatively small application so context seemed appropriate, and was a recommended solution. I've read the docs on react, but some of it isn't super clear since it's written using class components. I did some reading on stackoverflow as well for similiar implementations, but the code was not consitent between answers so I've just hacked together my best version of making sense of the tool.
I think I've maybe goofed something relatively obvious but I'm not sure what yet. Any insight appreciated. My intuition is that I've just architected something incorrectly, but I'm not sure what.
The current application currently consoles:
Cannot access 'cards' before initialization
at App (App.jsx:30:1)
Here is App.jsx:
import { useState, useEffect, useContext } from "react";
import "./styles/App.css";
import FileHandler from "./Components/fileHandler";
import ImagePreviewer from "./Components/ImagePreviewer";
import { Header } from "./Components/Header";
import { Comparison } from "./Components/Comparison";
import { Table } from "./Components/Table";
import { backgroundQuery } from "./Components/backgroundQuery"
import { Footer } from "./Components/Footer";
import { DBContainer } from "./Components/DatabaseFunctions/DBContainer";
import { CardsContext } from "./Components/AppContext"
function App({user}) {
const context = useContext(CardsContext);
const [cards, setCards] = context[cards]
const [previewCard, setPreviewCard] = context[previewCard]
const [comparisonCards, setComparisonCards] = context[comparisonCards]
const [userDBCards, setUserDBCards] = context[userDBCards];
const [cardInput, setCardInput] = context[cardInput]
const [background, setBackground] = useState([]);
useEffect(() => {
backgroundQuery()
.then(data => {
setBackground(data.image_uris.art_crop);
})
.catch(error =>
console.log(error.message));
}, [setBackground]);
//insert user token into database
return (
<div id="master-div" className=".container" style={{
backgroundImage: `url(${background})`,
}}>
<Header
background={background}
setBackground={setBackground}
cards={cards}
user={user}
/>
<FileHandler
cardInput={cardInput}
setCardInput={setCardInput}
previewCard={previewCard}
setPreviewCard={setPreviewCard}
cards={cards}
setCards={setCards}
setComparisonCards={setComparisonCards}
user={user}
/>
<div className="main-container">
<Comparison
user={user}
userDBCards={userDBCards}
cards={cards}
setCards={setCards}
comparisonCards={comparisonCards}
setComparisonCards={setComparisonCards}
/>
</div>
<div className="row .container">
<div className="col-3 .container" id="preview-container">
<ImagePreviewer previewCard={previewCard} cards={cards} />
</div>
<div className="col-6 .container" id="tableContainer">
<DBContainer
user={user}
cards={cards}
setCards={setCards}
userDBCards={userDBCards}
setUserDBCards={setUserDBCards}
setComparisonCards={setComparisonCards}
/>
<Table
setComparisonCards={setComparisonCards}
setPreviewCard={setPreviewCard}
cards={cards}
setCards={setCards} />
</div>
</div>
<Footer />
</div>
);
}
export default App;
Below I have the code for my AppContext component which houses all of my context.
import { createContext, useState } from "react";
export const CardsContext = createContext();
export const BackgroundContext = createContext();
const AppContextProvider = ({children}) => {
const [cardInput, setCardInput] = useState([]);
const [cards, setCards] = useState([]);
const [previewCard, setPreviewCard] = useState([]);
const [comparisonCards, setComparisonCards] = useState([]);
const [userDBCards, setUserDBCards] = useState([]);
const [background, setBackground] = useState([]);
return(
<CardsContext.Provider value={{
cards: [cards, setCards],
cardInput: [cardInput, setCardInput],
previewCard: [previewCard, setPreviewCard],
comparisonCards: [comparisonCards, setComparisonCards],
userDBCards: [userDBCards, setUserDBCards]
}}>
<BackgroundContext.Provider value={[background, setBackground]}>
{children}
</BackgroundContext.Provider>
</CardsContext.Provider>
)
}
export default AppContextProvider
This is wrapped around all of my routes in my index here:
ReactDOM.render(
<BrowserRouter>
<Auth0ProviderWithRedirectCallback
domain={process.env.REACT_APP_DOMAIN}
clientId={process.env.REACT_APP_CLIENT_ID}
redirectUri={window.location.origin}
>
<AppContextProvider>
<Routes>
<Route path="/" element={<ProtectedRoute component={App}/>} />
<Route path="/profile/:id" element={<ProtectedRoute component={ProfilePage}/>} />
<Route path='/auth' element={<Auth />} />
{/* The below route should fire for upload list, rendering a page of thier cards. */}
<Route path='/profile/:id/:list' element={<ListPage />} />
</Routes>
</AppContextProvider>
</Auth0ProviderWithRedirectCallback>
</BrowserRouter>,
document.getElementById('root')
);
CodePudding user response:
You should wrap your context[cards]
in quotes like so context["cards"]
. Now the app tries to get the context with the value of cards
which is not defined yet.
Same for the other context[...]