1

I have a component included in my App.js and that component contains some common logic which needs to be executed.

So my App component JSX looks like

<CommonComponent />
    {canRenderBool && (
    <div class="container">
        <Route exact path="/comp1">
        <Comp1 />
        </Route>
        <Route exact path="/comp2">
        <Comp2 />
        </Route>
        </div>
)
}

Now, I want that on each route transition (e.g. user clicks on a new route url), I want that the code in CommonComponent (non-routable component) gets triggered. This common component has logic which returns a boolean variable and I kind of render/not render Comp1/Comp2 i.e. all the routes based on that boolean

What is the best way I can handle it. I want to avoid having that code defined/invoked in each component manually?

Also most of my components are functional/hooks based.

copenndthagen
  • 49,230
  • 102
  • 290
  • 442
  • Is CommonComponent the parent of comp1 and comp2? I see no closing tag. – Pelicer Sep 24 '21 at 11:22
  • 1
    Oh sorry...updated...No CommonComponent is child of App and kind of sibling to comp1 and comp2 – copenndthagen Sep 24 '21 at 11:31
  • Also just to add, this common component has logic which returns a boolean variable and I kind of render/not render Comp1/Comp2 i.e. all the routes based on that boolean – copenndthagen Sep 24 '21 at 11:32
  • Updated code so that you can get an idea – copenndthagen Sep 24 '21 at 11:34
  • I think this might help: https://stackoverflow.com/questions/41911309/how-to-listen-to-route-changes-in-react-router-v4. I'm thinking you can define canRenderBool as a state in the parent of your JSX, create a listener for the history object, and pass down the URL, for example, down to CommonComponent as a prop. This way, when the URL changes CommonComponent will be rerendered and if you pass setCanRenderBool to CommonComponent as a prop, you can inform the parent JSX of changes in that bool. – Pelicer Sep 24 '21 at 11:37
  • 1
    Actually in my case, this is in the App component...so no parent as such...Not sure if that would still work... – copenndthagen Sep 24 '21 at 11:46

2 Answers2

1

In case you are using functional component for your App Component. You can write your CommonComponent logic inside useEffect and then there you can set state for your canRenderBool flag

for example

import React, { useState, useEffect } from "react";
import { BrowserRouter as Router, Switch, Route, Link, useLocation } from "react-router-dom";

function App() {
  const [canRenderBool , setCanRenderBool] = useState(false);
  const location = useLocation(); // this will only work if you wrap your App component in a Router

  // this effect will run on every route change
  useEffect(() => {
    // your logic here
    // ..

    // set value of 'canRenderBool' flag
    setCanRenderBool(true);
  }, [location]);

  return (
    // Note that Router is not used here it will be wraped when we export this component, see below
    <Switch>
      <Route exact path="/">
        <Page1 />
      </Route>

      {canRenderBool && (
        <Route exact path="/page-2">
          <Page2 />
        </Route>
      )}
    </Switch>
  );
}

function Page1() {
  return (
    <div>
      <h1>
        Go to <Link to="/page-2">Page 2</Link>
      </h1>
    </div>
  );
}

function Page2() {
  return (
    <div>
      <h1>
        Go to <Link to="/">Page 1</Link>
      </h1>
    </div>
  );
}

// Wrapping Router around App and exporting
export default () => (
  <Router>
    <App />
  </Router>
);
0
{canRenderBool && (
 <Router>
  <div class="container">
      <Switch>
        <Route exact path="/comp1"> <Comp1 /> </Route>
        <Route exact path="/comp2"> <Comp2 /> </Route>
      </Switch>
    <Link to="/comp1">Component 1</Link>
    <Link to="/comp2">Component 2</Link>
  </div>
 </Router>
)
}

This might help. And you will need to import all keywords and components before using them.

Abdulhakim
  • 620
  • 8
  • 11