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!!
 
    