Categories
React

Add Icons into Our React App with React Icons

React Icons is a library with lots of icons we can add to our React app.

In this article, we’ll look at how to add icons to our React app with React Icons.

Installation

We can install the package by running:

npm install react-icons --save

Add Icons

Once we installed the package, we can add an icon by importing the icon component:

import React from "react";
import { FaBeer } from "react-icons/fa";

export default function App() {
  return (
    <h3>
      Lets go for a <FaBeer />?
    </h3>
  );
}

Ant Design Icons

We can add Ant Design icons with the react-icons/ai module:

import React from "react";
import { AiFillAccountBook } from "react-icons/ai";

export default function App() {
  return (
    <h3>
      <AiFillAccountBook />
    </h3>
  );
}

The full list of icons is at https://react-icons.github.io/react-icons/icons?name=ai

Bootstrap Icons

We can add Bootstrap icons with the react-icon/bs module:

import React from "react";
import { BsFillAlarmFill } from "react-icons/bs";

export default function App() {
  return (
    <h3>
      <BsFillAlarmFill />
    </h3>
  );
}

The full list of icons is at https://react-icons.github.io/react-icons/icons?name=bs

BoxIcons

We can add BoxIcons from the react-icon/bi module:

import React from "react";
import { BiAbacus } from "react-icons/bi";

export default function App() {
  return (
    <h3>
      <BiAbacus />
    </h3>
  );
}

The full list of icons is at https://react-icons.github.io/react-icons/icons?name=bi

Devicons

We can add Devicons from the react-icons/di module.

For instance, we write:

import React from "react";
import { DiAndroid } from "react-icons/di";

export default function App() {
  return (
    <h3>
      <DiAndroid />
    </h3>
  );
}

to add the Android icon.

The full list of Devicons is at https://react-icons.github.io/react-icons/icons?name=di

Feather Icons

We can add Feather Icons from the react-icons/fi module.

For example, we write:

import React from "react";
import { FiActivity } from "react-icons/fi";

export default function App() {
  return (
    <h3>
      <FiActivity />
    </h3>
  );
}

to add the activity icon.

The full list of icons is at https://react-icons.github.io/react-icons/icons?name=fi

Flat Color Icons

We can add Flat Color Icons from the react-icons/fc module.

For instance, we write:

import React from "react";
import { FcAbout } from "react-icons/fc";

export default function App() {
  return (
    <h3>
      <FcAbout />
    </h3>
  );
}

to add the about icon.

The full list of Flat Color icons is at https://react-icons.github.io/react-icons/icons?name=fc

Font Awesome

Font Awesome icons can be added with the react-icons/fa module.

To add one, we write:

import React from "react";
import { Fa500Px } from "react-icons/fa";

export default function App() {
  return (
    <h3>
      <Fa500Px />
    </h3>
  );
}

to add the Font Awesome icon.

The full list of icons can be found at https://react-icons.github.io/react-icons/icons?name=fa

Conclusion

We can add icons from various icon libraries into our React app with React Icons.

Categories
React

React App Routing with Wouter — Active Links, Trailing Slash, and Nested Paths

Wouter is a library that lets us loading React components according to URLs.

In this article, we’ll look at how to add routing to a React app with Wouter.

Active Links

We can set the active link by checking the isActive variable returned from the useRoute prop.

For instance, we can write:

import React from "react";
import { Link, Route, Router, useRoute } from "wouter";

const InboxPage = () => {
  return (
    <div>
      <p>inbox</p>
    </div>
  );
};

const UserPage = () => {
  const [, params] = useRoute("/users/:name");
  return <div>Hello, {params.name}!</div>;
};

const ActiveLink = (props) => {
  const [isActive] = useRoute(props.href);

  return (
    <Link {...props}>
      <a className={isActive ? "active" : ""}>{props.children}</a>
    </Link>
  );
};

export default function App() {
  return (
    <div>
      <style>
        {`.active {
            font-weight: bold
          }`}
      </style>
      <Router>
        <ActiveLink href="/users/foo">Users</ActiveLink>
        <ActiveLink href="/about">About</ActiveLink>
        <Route path="/about">
          <p>About Us</p>
        </Route>
        <Route path="/users/:name" component={UserPage}></Route>
        <Route path="/inbox" component={InboxPage} />
      </Router>
    </div>
  );
}

We have the ActiveLink component that calls the useRoute hook with the current URL and returns an array with the isActive variable.

isActive is true means the link for the current URL is active.

Trailing Slash

We can make Wouter match a route with the trailing slash with a custom URL matcher.

For instance, we can write:

import React from "react";
import { Route, Router } from "wouter";
import makeMatcher from "wouter/matcher";
import { pathToRegexp } from "path-to-regexp";

const customMatcher = makeMatcher((path) => {
  let keys = [];
  const regexp = pathToRegexp(path, keys, { strict: true });
  return { keys, regexp };
});

export default function App() {
  return (
    <div>
      <Router matcher={customMatcher}>
        <Route path="/foo">foo</Route>
        <Route path="/foo/">/foo/</Route>
      </Router>
    </div>
  );
}

We call makeMatcher with a callback to return an object with an object with strict set to true .

This will make sure that URLs with a trailing and without but otherwise are the same are considered different.

Nested Paths

We can add nested paths by setting the base path.

For instance, we can write:

import React from "react";
import { Link, Route, Router, useLocation, useRouter } from "wouter";

const NestedRoutes = (props) => {
  const router = useRouter();
  const [parentLocation] = useLocation();

  const nestedBase = `${router.base}${props.base}`;
  if (!parentLocation.startsWith(nestedBase)) return null;

  return (
    <Router base={nestedBase} key={nestedBase}>
      {props.children}
    </Router>
  );
};

export default function App() {
  return (
    <div>
      <Router>
        <Route path="/about">about</Route>
        <NestedRoutes base="/dashboard">
          <Link to="/users" />
          <Route path="/users">users</Route>
        </NestedRoutes>
      </Router>
    </div>
  );
}

We created the NestedRoutes component that takes the base prop to set the base path.

From it, we created the nestedBase variable by combining router.base and props.base to create the base path.

Then we set the base prop’s value to nestedBase to set the nested routes’ base path.

Conclusion

We can check which link is active, adding trailing slash matches, and nested paths with Wouter.

Categories
React

React App Routing with Wouter — Redirect, Default Route, and Base Path

Wouter is a library that lets us loading React components according to URLs.

In this article, we’ll look at how to add routing to a React app with Wouter.

Redirect

We can redirect to another route component with the setLocation function.

For instance, we can write:

import React from "react";
import { Route, Router, useLocation } from "wouter";

const InboxPage = () => {
  return (
    <div>
      <p>inbox</p>
    </div>
  );
};
export default function App() {
  const [, setLocation] = useLocation();

  return (
    <div>
      <a href="#" onClick={() => setLocation("/about")}>
        About
      </a>
      <Router>
        <Route path="/about">
          <p>About Us</p>
        </Route>
        <Route path="/users/:name">
          {(params) => <div>Hello, {params.name}!</div>}
        </Route>
        <Route path="/inbox" component={InboxPage} />
      </Router>
    </div>
  );
}

We call the useLocation hook to return the setLocation function.

Then we call that in the onClick handler to go to the /about route.

Matching Dynamic Segments

We can use the useRoute hook to match dynamic route segments.

For instance, we write:

import React from "react";
import { Link, Route, Router, useRoute } from "wouter";

const InboxPage = () => {
  return (
    <div>
      <p>inbox</p>
    </div>
  );
};

const UserPage = () => {
  const [, params] = useRoute("/users/:name");
  return <div>Hello, {params.name}!</div>;
};

export default function App() {
  return (
    <div>
      <Router>
        <Link href="/users/foo">Users</Link>
        <Route path="/about">
          <p>About Us</p>
        </Route>
        <Route path="/users/:name" component={UserPage}></Route>
        <Route path="/inbox" component={InboxPage} />
      </Router>
    </div>
  );
}

In the UserPage , we call the useroute hook with the route pattern to get the name parameter from the params oject.

In the Route ‘s path prop, we have the :name placeholder to add the placeholder.

We can also match the /foo?/:bar* pattern to add the wildcard bar placeholder.

/foo/baz? has the optional baz placeholder.

And /foo/bar+ with bar being one or more segments is also supported for matching.

Base Path

We can add a base path with the Router component’s base prop.

For instance, we write:

import React from "react";
import { Link, Route, Router, useRoute } from "wouter";

const InboxPage = () => {
  return (
    <div>
      <p>inbox</p>
    </div>
  );
};

const UserPage = () => {
  const [, params] = useRoute("/users/:name");
  return <div>Hello, {params.name}!</div>;
};

export default function App() {
  return (
    <div>
      <Router base="/app">
        <Link href="/users/foo">Users</Link>
        <Route path="/about">
          <p>About Us</p>
        </Route>
        <Route path="/users/:name" component={UserPage}></Route>
        <Route path="/inbox" component={InboxPage} />
      </Router>
    </div>
  );
}

to set the base path to /app .

Default Route

We can add a default route by adding the Route component without adding the path prop.

For instance, we write:

import React from "react";
import { Route, Switch } from "wouter";

export default function App() {
  return (
    <div>
      <Switch>
        <Route path="/about">
          <p>About Us</p>
        </Route>
        <Route>Not Found</Route>
      </Switch>
    </div>
  );
}

to add the Not Found route.

The default route should always come last so the other patterns can be checked before showing the not found route.

Conclusion

We can add redirects, match dynamic route segments, set the base path, and add a default route with Wouter into our React app.

Categories
React

React App Routing with Wouter — Route Changes, Switches, and Links

Wouter is a library that lets us loading React components according to URLs.

In this article, we’ll look at how to add routing to a React app with Wouter.

Watch Router Changes with useRouter

We can use the useRouter hook to watch for changes to the router object.

For instance, we write:

import React, { useEffect } from "react";
import { Link, Route, Router, useRouter } from "wouter";

const InboxPage = () => {
  return (
    <div>
      <p>inbox</p>
    </div>
  );
};

export default function App() {
  const router = useRouter();

  useEffect(() => {
    console.log(router);
  }, [router]);

  return (
    <div>
      <Link href="/inbox">
        <a>Inbox</a>
      </Link>
      <Router>
        <Route path="/about">
          <p>About Us</p>
        </Route>
        <Route path="/users/:name">
          {(params) => <div>Hello, {params.name}!</div>}
        </Route>
        <Route path="/inbox" component={InboxPage} />
      </Router>
    </div>
  );
}

We use the useEffect hook to watch for router changes.

router has the hook property, which is the useLocation hook by default.

Also, we can add our own properties to the router object to pass data between routes

Route Component

We can use the Route component to define routes.

For instance, we write:

import React, { useEffect } from "react";
import { Link, Route, Router, useRouter } from "wouter";

const InboxPage = () => {
  return (
    <div>
      <p>inbox</p>
    </div>
  );
};

export default function App() {
  return (
    <div>
      <Link href="/inbox">
        <a>Inbox</a>
      </Link>
      <Router>
        <Route path="/about">
          <p>About Us</p>
        </Route>
        <Route path="/users/:name">
          {(params) => <div>Hello, {params.name}!</div>}
        </Route>
        <Route path="/inbox" component={InboxPage} />
      </Router>
    </div>
  );
}

We add the Route component and set the path prop to define the routes.

:name is a URL parameter placeholder.

And we can get its value from the params parameter.

Link Component

The Link component lets us add links to let us navigate to different pages.

For instance, we write:

import React, { useEffect } from "react";
import { Link, Route, Router, useRouter } from "wouter";

const InboxPage = () => {
  return (
    <div>
      <p>inbox</p>
    </div>
  );
};

export default function App() {
  return (
    <div>
      <Link href="/about">
        <a>About</a>
      </Link>
      <Router>
        <Route path="/about">
          <p>About Us</p>
        </Route>
        <Route path="/users/:name">
          {(params) => <div>Hello, {params.name}!</div>}
        </Route>
        <Route path="/inbox" component={InboxPage} />
      </Router>
    </div>
  );
}

to add a link to go to the About page when we click it.

Switch Component

The Switch component lets us add exclusive routing into our React app.

It makes sure that only one route is rendered at a time.

For instance, we write:

import React from "react";
import { Link, Route, Switch } from "wouter";

const AllOrders = () => {
  return (
    <div>
      <p>all orders</p>
    </div>
  );
};

const Orders = ({ params }) => {
  return (
    <div>
      <p>orders {params.status}</p>
    </div>
  );
};

export default function App() {
  return (
    <div>
      <Link href="/orders/all">
        <a>All</a>
      </Link>
      <Switch>
        <Route path="/orders/all" component={AllOrders} />
        <Route path="/orders/:status" component={Orders} />
      </Switch>
    </div>
  );
}

We put the Route components in a Switch so that we only AllOrders or Orders but never both together.

In Orders , we get the URL parameters from the params prop.

Conclusion

We can add exclusive routes and watch for router changes in our React app with Wouter.

Categories
React

Add Routing to a React App with Wouter

Wouter is a library that lets us loading React components according to URLs.

In this article, we’ll look at how to add routing to a React app with Wouter.

Installation

To install it, we run:

npm i wouter

Getting Started

We can add routes to our React app by using the Route component.

For instance, we can write:

import React from "react";
import { Link, Route } from "wouter";

const InboxPage = () => <p>inbox</p>;

export default function App() {
  return (
    <div>
      <Link href="/users/1">
        <a className="link">Profile</a>
      </Link>

      <Route path="/about">About Us</Route>
      <Route path="/users/:name">
        {(params) => <div>Hello, {params.name}!</div>}
      </Route>
      <Route path="/inbox" component={InboxPage} />
    </div>
  );
}

We add the Router component to let us add map routes to React components.

:name is a URL parameter.

We can get its value with params.name .

Link lets us create links to load routes.

We can also add the component prop to add components as we did with InboxPage .

useRoute Hook

We can use the useRouter hook to extract URL parameters from a route.

For example, we write:

import React from "react";
import { Transition } from "react-transition-group";
import { useRoute } from "wouter";

export default function App() {
  const [match, params] = useRoute("/users/:id");

  return (
    <div>
      <Transition in={match}>
        <p>Hi, this is: {params.id}</p>
      </Transition>
    </div>
  );
}

We parse the route URL with tyhe useRoute hook by passing it into the hook.

Then we get the params object to get the URL parameters.

We also have the Transition component to add transitions when we load routes.

useLocation Hook

We can use the useLocation hook to return the location object to get go to a different route.

For example, we write:

import React from "react";
import { Link, Route, useLocation } from "wouter";

const InboxPage = () => {
  const [location, setLocation] = useLocation();

  return (
    <div>
      <p>{`The current page is: ${location}`}</p>
      <p>
        <a onClick={() => setLocation("/about")}>Click to update</a>
      </p>
    </div>
  );
};

export default function App() {
  return (
    <div>
      <Link href="/inbox">
        <a>Inbox</a>
      </Link>
      <Route path="/about">
        <p>About Us</p>
      </Route>
      <Route path="/users/:name">
        {(params) => <div>Hello, {params.name}!</div>}
      </Route>
      <Route path="/inbox" component={InboxPage} />
    </div>
  );
}

to add a link to the InboxPage component.

The link uses the useLocation hook’s setLocation function to go to the about route.

So when we click the Click to update link, we see About us.

Customizing the Location Hook

We can customize the useLocation hook to do what we want.

For instance, we can extract URL segments from the hash instead of from URL parameters.

To do this, we write:

import React, { useCallback, useEffect, useState } from "react";
import { Link, Route, Router, useLocation } from "wouter";

const currentLocation = () => {
  return window.location.hash.replace(/^#/, "") || "/";
};

const useHashLocation = () => {
  const [loc, setLoc] = useState(currentLocation());

  useEffect(() => {
    const handler = () => setLoc(currentLocation());
    window.addEventListener("hashchange", handler);
    return () => window.removeEventListener("hashchange", handler);
  }, []);
  const navigate = useCallback((to) => (window.location.hash = to), []);
  return [loc, navigate];
};

const InboxPage = () => {
  const [location] = useLocation();

  return (
    <div>
      <p>{`The current page is: ${location}`}</p>
    </div>
  );
};

export default function App() {
  return (
    <div>
      <Link href="/inbox">
        <a>Inbox</a>
      </Link>
      <Router hook={useHashLocation}>
        <Route path="/about">
          <p>About Us</p>
        </Route>
        <Route path="/users/:name">
          {(params) => <div>Hello, {params.name}!</div>}
        </Route>
        <Route path="/inbox" component={InboxPage} />
      </Router>
    </div>
  );
}

We have the currentLocation function that gets the part of the URL after thw hash.

Then we pass that into the useState hook to set the initial URL hash value.

And we listen for hashchange events to get the changes to the hash part of the URL.

If there are any changes, we return the loc location.

navigate navigates to the hash part of the URL.

Then we pass the hook into the hook prop to use it.

So now when we go to /#/users/1 , we see Hello, 1! displayed.

When we go to /#/inbox , we see The current page is: /inbox

And going to /#/about renders About Us .

Conclusion

Wouter is a lightweight router for React apps.