Search code examples
reactjsredux

grandchild component doesn't recognize the global state react redux


Hello everyone and thank you for reading,

I'm new to redux and Iv been trying to connect a grandchild component with the store, but for some reason It doesn't work.

The child component (called canvas) uses the store as well and doesn't show any problem, but when I'm trying to get the same data in a component I call from within the child component I get: "Uncaught Error: could not find react-redux context value; please ensure the component is wrapped in a Provider tag"

I searched for the solution on the internet and everybody suggests to wrap the app component in provider tags inside index.js, but I already did that in the beginning

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {createStore} from 'redux';
import allReducer from './reducers'
import { Provider } from 'react-redux';
const store = createStore(allReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());




ReactDOM.render(
  // <React.StrictMode>
    <Provider store={store}>
      <App/>
    </Provider>,
  //</React.StrictMode>,
  document.getElementById('root')
);

App.js

import React from 'react';
import "./App.css";
import { Canvas } from "./components/Canvas";


export default function App() {
 
  return (
    
    <div className="main-div">
     
        <Canvas/>
      
    </div>
  );
}

relevant data from canvas.js (child component)

import { Stage, Layer, Rect  } from 'react-konva';
.
.
.
.
const theTextObjs = TextObjs.map((text,key) => {
    
    return (
      

      <TextBox
        //some irrelevant props
      /> 
       {/* some irrelevant info and other components . . . */}
   
  )});
.
.
.
.

return(
 <Stage
           
            width={ window.innerWidth * 2}
            height={ window.innerHeight * 2}
            //style={{ border: '1px solid grey' }}
            ref={stageRef}
           
            
           
          
          >
            <Layer>
              <Rect
              x = {0}
              y= {0}
              width={ window.innerWidth * 2}
              height={ window.innerHeight * 2}
              fill={"white"}
              stroke={"white"}
              strokeWidth={5}
             
              />
             
              {theTextObjs}
              

            </Layer>
          </Stage>
//some more components
)

inside of TextBox.js (grandchild component)

import React from "react";


import { useSelector} from 'react-redux';


export function TextBox({textEditVisible, textX,fill,textY,textValue,fontSize,width,height,fontStyle,align,id,onDragStart,isSelected,onClick,onChangeEnd,onContextMenu,onChangeEdit,onClickedit,onKeyDownEdit,event}) {

  const selectedTextObj = useSelector(state => state.selectedTextObj)
  const TextObjs = useSelector(state => state.TextObjs)
  const dispatch = useDispatch()
 //
 //some irrelevant info
 // ...
  
  return (
      <>
            {/* more irrelevant info */}
    </>
  );
}

Solution

  • When using a different React renderer such as Konva, you need to wrap the components within the different Renderer within a new provider. In the case of Konva, the children of Stage.

    See this issue.

    const store = useStore()
    
    return ( <Stage
               
                width={ window.innerWidth * 2}
                height={ window.innerHeight * 2}
                //style={{ border: '1px solid grey' }}
                ref={stageRef}
               
                
               
              
              >
               <Provider store={store}>
                <Layer>
                  <Rect
                  x = {0}
                  y= {0}
                  width={ window.innerWidth * 2}
                  height={ window.innerHeight * 2}
                  fill={"white"}
                  stroke={"white"}
                  strokeWidth={5}
                 
                  />
                 
                  {theTextObjs}
                  
    
                </Layer>
               </Provider>
              </Stage>