-2

I am using ReactTransitionGroup with ReactRouter.
The goal is to reroute smoothly from one component to another. The problem - is that the component is rendered twice.

An example of a component (view) that renders twice

I am using the console to check. You might say that this is not critical. But, the problem is that because of this problem, 2 requests go to the server (one extra). Therefore, it is desirable for me to get rid of this bug.

This is the component itself - the switch

When switching a route, the console issues logs twice

I need to figure out why the side effect is being called twice. If there is not enough information, then write comments. I will try to answer as quickly as possible.

Here's an example from the documentation. I have achieved this effect, but the problem has already been described.

UPD: I remember very well that once it worked like a clockwork. But, probably, I myself did not notice that I changed something, which led to this problem.

UPD: If you need a code, then please, the required elements:

const TabList = ({ tabs }) => {
  return (
    <nav className="p-my-company__tabs">
      {tabs.map(({ to, label, id }) => (
        <NavLink to={to} key={id}>
          <div>{label}</div>
        </NavLink>
      ))}
    </nav>
  );
};
const TabViews = ({ tabViews }) => {
  const location = useLocation();

  return (
    <div className="p-my-company__views">
      <TransitionGroup>
        <SwitchTransition mode="out-in">
          <CSSTransition
            key={location.pathname}
            classNames={{
              enter: 'move-enter',
              enterActive: 'move-enter-active',
              exit: 'move-exit',
            }}
            timeout={100}>
            <Switch>
              {tabViews.map(({ path, Component, id }) => (
                <Route path={path} render={() => <Component />} key={id} />
              ))}
            </Switch>
          </CSSTransition>
        </SwitchTransition>
      </TransitionGroup>
    </div>
  );
};
<div className="p-my-company__panel">
  <TabList
    tabs={[
      { to: ROUTES.COMMON_INFO, label: 'Общая информация', id: 1 },
      { to: ROUTES.SHOWCASE, label: 'Моя витрина', id: 2 },
    ]}
  />

  <TabViews
    tabViews={[
      { path: ROUTES.COMMON_INFO, Component: CommonView, id: 1 },
      { path: ROUTES.SHOWCASE, Component: ShowCaseView, id: 2 },
    ]}
  />
</div>
const ShowCase = () => {
  useEffect(() => {
    console.log(2);
  }, []);

  return <div>ShowCase</div>;
};
  • @arun-kumar-mohan, I just tried to recreate an example that contains everything you need. You can use it. Click on any of the links and watch the console: [link to example](https://codesandbox.io/s/frosty-cherry-5udsk?file=/src/styles.scss) – Андрей Добрин Mar 15 '21 at 01:38

1 Answers1

1

Looks like the Switch component from React Router and React Transition Group don't work well together. The docs recommend avoiding the usage of the Switch component and passing a function to the Route's children prop. Since the function will be called regardless of whether there is a match or not, you can conditionally render Component if there's one.

<>
  {tabViews.map(({ path, Component }) => (
    <Route exact path={path} key={path}>
      {({ match }) => (
        <TransitionGroup>
          <SwitchTransition mode="out-in">
            <CSSTransition
              in={match != null}
              classNames={{
                enter: 'move-enter',
                enterActive: 'move-enter-active',
                exit: 'move-exit',
              }}
              timeout={100}
              unmountOnExit
              key={location.pathname}
            >
              <div className="page">{match && <Component />}</div>
            </CSSTransition>
          </SwitchTransition>
        </TransitionGroup>
      )}
    </Route>
  ))}
</>

Edit react-router-transition-group-x5f9r

Arun Kumar Mohan
  • 11,517
  • 3
  • 23
  • 44