I'm brand new to the useContext
hook and trying to figure out what I'm doing wrong... without the top imports, here's what my code looks like:
So the root of my project looks like this:
export default function App() {
return (
<div className="App">
<AppProvider>
<Header/>
<Toolbar/>
<Canvas/>
<Imports/>
<Footer/>
</AppProvider>
</div>
);
}
Then I have a separate file called AppProvider that has this:
const CanvasItems = createContext();
const UpdateCanvasItems = createContext();
export function useCanvasItems() {
return useContext(CanvasItems)
}
export function useChangeItems() {
return useContext(UpdateCanvasItems)
}
export default function AppProvider({children}) {
const [state, setState] = useState({
imports: [],
images: [],
text: [],
circles: [],
rectangles: [],
draw: [],
})
// function pushes new items in to state object
function addCanvasItem(type, source) {
if (type === 'import') {
const tempState = [...state.imports];
tempState.push({id: Date.now(), image: source});
setState({...state, imports: tempState})
} else if (type === 'image') {
const tempState = [...state.images];
tempState.push({
id: Date.now(),
src: source.src,
x: window.innerWidth * Math.random(),
y: window.innerHeight * Math.random(),
})
setState({...state, images: tempState})
}
console.log("state after new item added:", state)
}
return (
<CanvasItems.Provider value={state}>
<UpdateCanvasItems.Provider value={addCanvasItem}>
{children}
</UpdateCanvasItems.Provider>
</CanvasItems.Provider>
)
}
I don't have any problems passing the state
object and the addCanvasItems
function down to the first level of children (so Header, Toolbar, Canvas, etc.) but I have children inside those components where I can't access the values.
For clarity - inside the Canvas
component, I have a Stage
component, inside that there's a Layer
component, inside that there's an Items
component (I'm using Konva and need to have all this nesting).
export default function Canvas() {
const { onDrop, onDragOver } = useDragDrop;
const state = useCanvasItems();
useEffect(() => {
console.log("state in canvas", state)
}, [state])
return (
<div id='canvas'>
<Stage
container='canvas'
onDrop={onDrop}
onDragOver={onDragOver}
>
<Layer>
<Items/>
</Layer>
</Stage>
</div>
)
}
I need to access the state
object in the Items
component but I want to avoid prop drilling. For testing, I created a useEffect
function to print the state every time it changes. The Items
component prints undefined
on the first load, whereas the Canvas
component prints the full object.
export default function Items() {
const state = useCanvasItems();
useEffect(() => {
console.log("state in items", state)
}, [state])
return (
<>
{state && state.images.map(image => {
return <NewImage image={image} />
})}
</>
)
};
what prints to the console on load and after a file is imported (changing the state)
What am I missing with this hook and how to implement it??
MANY thanks for the help!!