fefe
fefe

Reputation: 9055

How to debug React Router?

I'm trying to use React Router in my react app which is bounded as wordpress plugin and uses flux to fetch api data.

my entry point looks as it follows

import React from 'react';
import Workshops  from './components/workshops';
import Workshop  from './components/workshop';
import NotFound  from './components/notfound';
import Router, { Route, DefaultRoute, NotFoundRoute, Redirect, Link } from 'react-router';
import json  from './config.json';
localStorage.clear();
localStorage.setItem('workshops', JSON.stringify(json));

const AppRoutes = (
   <Route path="/" handler={Workshops}>
    <DefaultRoute handler={Workshop} />
    <Route name="workshop" path=":slug" handler={Workshop}/>
    <NotFoundRoute handler={NotFound} />
  </Route>
);

Router.run(AppRoutes, Router.HashLocation, (Root) => {
  React.render(<Root />, document.getElementById('workshop-booker'));
});

than in my Workshops component I make some links to a given route, I have hash changes but the routed component does not getting fired.

<h3> <Link to="workshop" params={{slug: workshop.slug }}> {workshop.title.rendered }</Link></h3>

Upvotes: 40

Views: 45068

Answers (5)

hitautodestruct
hitautodestruct

Reputation: 20820

For anyone using createBrowserRouter

Here is a debug function to use:

import { createBrowserRouter } from 'react-router-dom';

function createDebugRouter(routes, opts) {
  const router = createBrowserRouter(routes, opts);
  
  // Store the original navigator function
  const originalNavigate = router.navigate;
  
  // Log initial state
  console.log('Initial router state:', {
    basename: router.basename,
    state: router.state,
    routes: router.routes,
  });

  // Override the navigate function to add logging
  router.navigate = (...args) => {
    console.log('Navigation requested:', {
      args,
      currentLocation: router.state.location,
      currentAction: router.state.navigation.action,
    });
    return originalNavigate.apply(router, args);
  };

  // Add listener for all location changes
  router.subscribe((state) => {
    console.log('Router state updated:', {
      location: state.location,
      action: state.navigation.action,
      state: state.navigation.state,
      error: state.navigation.error,
    });
  });

  return router;
}

const router = createDebugRouter([
  {
    path: '*',
    element: <NotFound />,
  },
  {
    path: '/',
    element: <App />,
    children: [
      {
        path: `/home`,
        element: <Home />
      }
    ]
  }
])

export default router;

Upvotes: 1

JillAndMe
JillAndMe

Reputation: 4551

I made my DebugRouter for functional components

const DebugRouter = ({ children }: { children: any }) => {
  const { location } = useHistory()
  if (process.env.NODE_ENV === 'development') {
    console.log(
      `Route: ${location.pathname}${location.search}, State: ${JSON.stringify(location.state)}`,
    )
  }

  return children
}

const Router = () => {
  return (
    <BrowserRouter>
      <Layout>
        <Route
          render={() => {
            return (
              <DebugRouter>
                <Switch>
                  <Redirect exact from="/" to={...} />
                  // <Route/> should be here

                  <Redirect from="*" to={...} />
                </Switch>
              </DebugRouter>
            )
          }}
        />
      </Layout>
    </BrowserRouter>
  )
}

Upvotes: 26

Moshe Malka
Moshe Malka

Reputation: 536

You can wrap your Router with a DebugRouter which will print the navigation actions made:

import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Login from 'components/Login'
import DefaultComponent from 'components/DefaultComponent'

class DebugRouter extends BrowserRouter {
  constructor(props){
    super(props);
    console.log('initial history is: ', JSON.stringify(this.history, null,2))
    this.history.listen((location, action)=>{
      console.log(
        `The current URL is ${location.pathname}${location.search}${location.hash}`
      )
      console.log(`The last navigation action was ${action}`, JSON.stringify(this.history, null,2));
    });
  }
}

class App extends Component {
  render() {
    return (
      <DebugRouter>
        <Switch>
          <Route exact path="/login" name="Login Page" component={Login} />
          <Route path="/" name="Home" component={DefaultComponent} />
        </Switch>
      </DebugRouter>
    );
  }
}

link to the gist

Upvotes: 52

Lucas Matos
Lucas Matos

Reputation: 2918

You can use the following code to debug React Router:

console.log(this.props.location)
console.log(this.props.match)

Upvotes: -4

cesarve
cesarve

Reputation: 272

You can try something like this

import React, {Component} from 'react';
import PropTypes from 'prop-types'
import {withRouter} from "react-router-dom";

class RouterDebugger extends Component {
    componentWillUpdate(nextProps, nextState){
        console.log('componentWillUpdate',nextProps, nextState)
    }
    componentDidUpdate(prevProps) {
        console.log('componentDidUpdate',prevProps)

    }

    render() {
        return null
    }
}

export default withRouter(RouterDebugger)

And insert this component in any place you want to debug. You can pass a prop with some identifier i hope this help you

Upvotes: 3

Related Questions