skip to Main Content

I have 3 components: Main.jsx (red), GridControl.jsx (blue), and Grid.jsx (green).

The purpose of the grid control is to save, undo, and redo edits made to the grid below. Understandably, this depends heavily on a lot of logic and data found in Grid.jsx.

So the easiest thing to do would be to include GridControl in Grid, so that Grid can pass information down to GridControl.

However, I really want the grid control buttons to be aligned with the other buttons in Main (the dropdowns and ‘get data’), for which it is easier to leave GridControl in Main and try to access the Grid’s save, undo and redo logic from there. It does feel like doing so would break React’s design patterns though, so I’m really no sure what to do.

Is there a neat way to go about this without putting everything in one component or breaking design patterns? I would really appreciate some help here, looking to learn the ‘right way’ to go about using React in tricky situations like these. Would calling Grid’s functions from Main to pass into GridControl indeed be bad practice?

Here is the return statement I currently have in Main.jsx (this makes it easy to align all the buttons, but I need to find a reliable way to make the grid control work):

return (
    <div id='mainpage'>
        <div id='filters-and-grid-controls'>
            <div id='dropdowns'>
                <Dropdown2 value={version} label='Version' options={versions} setter={setVersion} />
                <Dropdown2 value={period} label='Period' options={periods} setter={setPeriod} />
                <button id="get-data" className="button" onClick={handleGetData}>Get Data</button>
            </div>
            <GridControl />
        </div>
        <Grid gridData={gridData} getDataAfterSave={handleSave} />
    </div>
);

2

Answers


  1. You can simply create a context in your Main component something like this:

    export const MyContext = createContext(null);
    // ...
    const Main = () => {
     const [data, setData] = useState();
     return (
     <MyContext.Provider value={{ data, setData }}>
        // ...
        <GridControl />
        <Grid />
        // ...
     </MyContext.Provider>
    );
    }
    

    Now since GridControl and Grid are wrapped within MyContext.Provider they can have access to the provided values i.e data and setData you just have to use the context

    import {MyContext} from './main'
    const Grid = () => {
    const {data, setData} = useContext(MyContext)
    // ...
    }
    

    see useContext

    Login or Signup to reply.
  2. Will depend how complex is your logic inside of Grid.

    To resume your problem you need pass data between siblings components.

    To archive this create the data that you need use in GridControl on the parent component and then pass to Grid and GridControl.

    This is a minimal example

    const Main = () => {
      const [shareData, setShareData] = useState(null);
      // Create other share function here
      // Also you can pass the setShareData and mutate the state down
      return (
        <div>
          <Grid shareData={shareData} setShareData={setShareData}>
            hello
          </Grid shareData={shareData} setShareData={setShareData}>
          <GridControl>hello</GridControl>
        </div>
      );
    };
    
    const Grid = ({shareData, setShareData}) => {
      return (
        <div>
          <h1>shareData</h1>
          <Button onClick={() => setShareData('hello')}>Click me</Button>
        </div>
      );
    };
    
    const GridControl = ({shareData, setShareData}) => {
      return (
        <div>
          <h1>shareData</h1>
        </div>
      );
    };
    

    Other option is use a library to manage global states like context or redux, but I don’t recommend that to your case. These are more when you need pass data deeply in your app.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search