5

Previously, in react-router-dom v5 (or below) you could use:

<Route path="/" render={() => {doSomething(); return <ComponentName />}} />

to both fire a function and create a route without having to create any extra code inside of the ComponentName component. With render being replaced with element in v6, how do you now accomplish this?

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
DORRITO
  • 621
  • 2
  • 8
  • 25
  • What does `doSomething` do? Doing side effects during rendering isn't usually a good idea. The code should probably be called in a `useEffect`. – Nicholas Tower Dec 13 '21 at 22:12
  • In this specific case, it involves analytics. The above is a nice succinct way to add a helpful tracker (which only fires once) to many routes in one location without having to add that useEffect in each component. Simple and DRY. – DORRITO Dec 13 '21 at 22:22

2 Answers2

8

In react-router-dom v6 there are no longer any props to render a function in the Route, there exists the element prop that takes a JSX literal. Create a wrapper component that issues the side-effect, and wrap the component you are rendering on the route. Use the useEffect hook as unintentional side-effects in React should be avoided.

const DoSomethingWrapper = ({ children }) => {
  useEffect(() => {
    doSomething();
  }, []);
  return children;
};

...

<Route
  path="/"
  element={(
    <DoSomethingWrapper>
      <ComponentName />
    </DoSomethingWrapper>
  )}
/>
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
1

This is the answer I came up with:

const doSomething = (arg1, component) => {
  //posting arg1 as an example of whatever you are wanting to do.
  console.log(arg1);
  return component;
};
<Route path="/" element={doSomething("string", <Home />)} />

Edit* Marking this as the answer since it is most similar to the code in the original question, but is is not the only correct answer. Please consider the other great answer/s, which may be more appropriate, depending on your needs.

DORRITO
  • 621
  • 2
  • 8
  • 25