DEV Community

Cover image for React and Vue Syntax Comparison Side by Side Part2: Router
Andrew
Andrew

Posted on

React and Vue Syntax Comparison Side by Side Part2: Router

This is the second post about React and Vue syntax comparison. In this article, we compare the syntax for the most famous routing library in both ecosystems.

GitHub logo oahehc / react-vue-comparison

Comparing the syntax of React.js/Next.js and Vue.js/Nuxt.js side by side

Agenda


Basic-Routing

React-Router

import { BrowserRouter, Switch, Route } from 'react-router-dom';

export default function App() {
  return (
    <BrowserRouter>
      <div>
        <Switch>
          <Route path="/about" component={About} />
          <Route path="/" component={Home} />
        </Switch>
      </div>
    </BrowserRouter>
  );
}
Enter fullscreen mode Exit fullscreen mode

Vue-Router

const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar },
];
const router = new VueRouter({
  mode: 'history',
  routes,
});
const app = new Vue({ router }).$mount('#app');
Enter fullscreen mode Exit fullscreen mode
<div id="app">
  <router-view></router-view>
</div>
Enter fullscreen mode Exit fullscreen mode

Dynamic-Routing

React-Router

import { BrowserRouter, Route } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <div>
        <Route path="/contact/:id" component={Contact} />
      </div>
    </BrowserRouter>
  );
}

...

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

function Contact() {
  let { id } = useParams();

  return ...;
}
Enter fullscreen mode Exit fullscreen mode

Vue-Router

const router = new VueRouter({
  mode: 'history',
  routes: [{ path: '/contact/:id', component: Contact }],
});

export default {
  computed: {
    id() {
      return this.$route.params.id;
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

Nested-Routing

React-Router

import { BrowserRouter, Route } from 'react-router-dom';

const App = () => (
  <BrowserRouter>
    <div>
      <Route path="/tacos" component={Tacos} />
    </div>
  </BrowserRouter>
);

...

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

const Tacos = ({ match }) => (
  <div>
    {/* here's a nested Route, match.url helps us make a relative path */}
    <Route path={match.url + '/carnitas'} component={Carnitas} />
  </div>
);
Enter fullscreen mode Exit fullscreen mode

Vue-Router

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
      children: [
        {
          path: 'profile',
          component: UserProfile,
        },
        {
          path: 'posts',
          component: UserPosts,
        },
      ],
    },
  ],
});

const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `,
};
Enter fullscreen mode Exit fullscreen mode

Link

React-Router

<Link
  to={{
    pathname: '/courses',
    search: '?sort=name',
    hash: '#the-hash',
    state: { fromDashboard: true },
  }}
>
  courses
</Link>
Enter fullscreen mode Exit fullscreen mode

Vue-Router

<router-link to="/courses">courses</router-link>
Enter fullscreen mode Exit fullscreen mode

NavLink

NavLink is used to display different style when current URL match to the link.

React-Router

<NavLink to="/react" activeClassName="react">
  React
</NavLink>
Enter fullscreen mode Exit fullscreen mode

Vue-Router

router-link automatically gets the .router-link-active class when its target route is matched.

<router-link to="/vue">vue</router-link>
Enter fullscreen mode Exit fullscreen mode

Get-Location

React-Router

  • Function component
import { useLocation } from "react-router-dom";

function App() {
  const location = useLocation();

  return ...;
}
Enter fullscreen mode Exit fullscreen mode
  • Class component
import { withRouter } from "react-router";

class App extends React.Component {
  static propTypes = {
    location: PropTypes.object.isRequired
  };

  render() {
    const { location } = this.props;

    return ...;
  }
}
export default withRouter(App);
Enter fullscreen mode Exit fullscreen mode

Vue-Router

export default {
  computed: {
    path() {
      return this.$route.path;
    },
    params() {
      return this.$route.params;
    },
    query() {
      return this.$route.query;
    },
    hash() {
      return this.$route.hash;
    },
    fullPath() {
      return this.$route.fullPath;
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

Push

React-Router

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

function HomeButton() {
  const history = useHistory();

  function handleClick() {
    history.push('/home');
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

Vue-Router

export default {
  methods: {
    toHome() {
      this.$router.push('/home');
    },
    toUser(id) {
      this.$router.push({ name: 'user', params: { userId: id } });
    },
    toRegister(id) {
      // /register?plan=private
      this.$router.push({ path: 'register', query: { plan: 'private' } });
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

Replace

replacing the current entry instead of push a new entry onto the history stack.

React-Router

<Link to="/courses" replace />;

// or

const history = useHistory();

function handleClick() {
  history.replace('/courses');
}
Enter fullscreen mode Exit fullscreen mode

Vue-Router

<router-link :to="/courses" replace />
Enter fullscreen mode Exit fullscreen mode

or

export default {
  methods: {
    toHome() {
      this.$router.replace('/home');
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

Redirect

React-Router

<Redirect to="/login" />
<Redirect from="/invoices" to="/invoices/dashboard" />
// push a new entry onto the history instead of replacing the current one.
<Redirect push to="/somewhere/else" />
Enter fullscreen mode Exit fullscreen mode

Vue-Router

const router = new VueRouter({
  routes: [{ path: '/a', redirect: { name: 'foo' } }],
});
Enter fullscreen mode Exit fullscreen mode

Event

React-Router

  • Function component
import { useHistory } from 'react-router-dom';

function App() {
  const history = useHistory();

  useEffect(() => {
    const unlisten = this.props.history.listen(...);
    return () => unlisten();
  }, [])

  return ...;
}
Enter fullscreen mode Exit fullscreen mode
  • Class component
import { withRouter } from "react-router";

class App extends React.Component {
  static propTypes = {
    history: PropTypes.object.isRequired
  };

  componentDidMount() {
    this.unlisten = this.props.history.listen(...);
  }

  componentWillUnmount() {
    if (this.unlisten && typeof this.unlisten === 'function') {
      this.unlisten();
    }
  }

  render() {
    return ...;
  }
}
export default withRouter(App);
Enter fullscreen mode Exit fullscreen mode

Vue-Router

  • global
const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => { ... })
router.afterEach((to, from) => { ... })
Enter fullscreen mode Exit fullscreen mode
  • by route
const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => { ... }
    }
  ]
})
Enter fullscreen mode Exit fullscreen mode

by component

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) { ... },
  beforeRouteUpdate (to, from, next) { ... },
  beforeRouteLeave (to, from, next) { ... },
}
Enter fullscreen mode Exit fullscreen mode

Scroll

React-Router

Because browsers are starting to handle the default case and apps have varying scrolling needs, React-Router don’t ship with default scroll management.

https://reacttraining.com/react-router/web/guides/scroll-restoration

export default function ScrollToTop() {
  const { pathname } = useLocation();

  useEffect(() => {
    window.scrollTo(0, 0);
  }, [pathname]);

  return null;
}
Enter fullscreen mode Exit fullscreen mode

Vue-Router

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return desired position
    if (savedPosition) {
      return savedPosition
    } else {
      return { x: 0, y: 0 }
    }
  }
})
Enter fullscreen mode Exit fullscreen mode

Lazy-Loading-and-Code-Splitting

If you are using Babel, you will need to add the syntax-dynamic-import plugin so that Babel can properly parse the syntax.

React-Router

https://github.com/gregberge/loadable-components

import loadable from '@loadable/component';

const LoadableComponent = loadable(() => import('./Dashboard.js'), {
  fallback: <Loading />,
});
Enter fullscreen mode Exit fullscreen mode

Vue-Router

const Foo = () => import('./Foo.vue');

const router = new VueRouter({
  routes: [{ path: '/foo', component: Foo }],
});
Enter fullscreen mode Exit fullscreen mode

Reference

Top comments (0)