Code Monkey home page Code Monkey logo

navigo-react's Introduction

navigo-react

Navigo router for React.

Quick example

import { Switch, Route } from "navigo-react";

export default function App() {
  return (
    <>
      <nav>
        <a href="/" data-navigo>Home</a>
        <a href="/package" data-navigo>Package</a>
      </nav>
      <Switch>
        <Route path="/package">
          Package documentation <a href="https://github.com/krasimir/navigo-react">here</a>.
        </Route>
        <Route path="/">
          NavigoReact is a router for React applications based on Navigo
          project.
        </Route>
      </Switch>
    </>
  );
}

Live demo here https://codesandbox.io/s/navigo-react-example-w9l1d.

Navigating between routes

The navigation in Navigo happens in two ways:

  • Via <a> tags. The only requirement is to add data-navigo attribute to the link. For example <a href="/users/list" data-navigo>View users</a>. For more details on the exact API check out this page.
  • Via the navigate or navigateByName methods. First you have to access the router with getRouter() and then use one of these two methods. For example:
import { getRouter } from 'navigo-react';

// Somewhere in your React components
<button onClick={() => getRouter().navigate('/users/list')}>
  View users
</button>

// or if you have a named route like
<Route path="/users/:id/:action" name="user">
  ...
</Route>

// Somewhere in your React components
<button
  onClick={
    () => getRouter().navigateByName('name', { id: 'xxx', action: 'view' })
  }>
  View users
</button>

Components

Route

<Route
  path="/user/:id"
  name="my-route-name"
  before={ (cb) => {} }
  after={ (cb) => {} }
  already={ (cb) => {} }
  leave={ (cb) => {} }>
  <p>Hey</p>
</Route>

The basic building block. Shortly, it's a component that renders its children based on the path prop.

Prop type required Description
path string yes Specifies the path for which the children will be rendered. URL parameters are supported with the well known syntax /users/:id/:action. You can access the values via the useNavigo hook
name string no Sets a name of the route so we can later navigate to it easily. Check out this section for an example
before function no It sets a function that is executed before the route gets switched. Checkout Hooking to the routing lifecycle section to see how to use it.
after function no It sets a function that is executed after the route gets switched. Checkout Hooking to the routing lifecycle section to see how to use it.
already function no It sets a function that is executed the current route is equal to the one specified. Or in other words - in case you land on the same route again. Checkout Hooking to the routing lifecycle section to see how to use it.
leave function no It sets a function that is executed when the user is about to leave the route. Checkout Hooking to the routing lifecycle section to see how to use it.

Route lifecycle functions

The before, after, already and leave are functions that execute during the route resolving. They give you the opportunity to hook some logic to each one of this moments and pause/reject some of them. Each of this functions receive an object:

function example
before function handleBefore({ render, done, match }) {...}
after function handleBefore({ render, match }) {...}
already function handleBefore({ render, match }) {...}
leave function handleBefore({ render, done, match }) {...}

Where render gives you an opportunity to render the children of the <Route> by setting data into the Navigo context. For example:

import { Route, useNavigo } from "navigo-react";

function Print() {
  const { pic } = useNavigo();

  if (pic === null) {
    return <p>Loading ...</p>;
  }
  return <img src={pic} width="200" />;
}

export default function App() {
  async function before({ render, done }) {
    render({ pic: null });
    const res = await (
      await fetch("https://api.thecatapi.com/v1/images/search")
    ).json();
    render({ pic: res[0].url });
    done();
  }
  return (
    <>
      <nav>
        <a href="/cat" data-navigo>
          Get a cat fact
        </a>
      </nav>
      <Route path="/cat" before={before}>
        <Print />
      </Route>
    </>
  );
}

Pay attention to the before function inside the <App> component. render calls trigger rendering of the <Print> component with specific context which we can access via the useNavigo hook. Finally when we are ready we call done() to indicate that the routing could be fully resolved. Which means changing the browser's URL and potentially executing after or already lifecycle methods.

We can completely block the routing to specific place by calling done(false). For example:

export default function App() {
  const [authorized, loggedIn] = useState(false);
  const before = (cb) => {
    if (!authorized) {
      cb(false);
    } else {
      cb(true);
    }
  };

  return (
    <>
      <Route path="/user" before={before}>
        <User />
      </Route>
    </>
  );
}

(Full example here)

Navigating using named routes

Sometimes we need to construct a URL based on some data. The library offers an imperative API for that:

import { getRouter, Route } from "navigo-react";

export default function App() {
  return (
    <>
      <button
        onClick={() => {
          getRouter().navigateByName("my-user", { id: "xxx" });
        }}
      >
        Click me
      </button>
      <Route path="/user/:id" name="my-user">
        I'm a user
      </Route>
    </>
  );
}

https://codesandbox.io/s/navigo-react-named-routes-0h2bh

Switch

<Switch>
  <Route path="/about">About</Route>
  <Route path="/products">Products</Route>
  <Route path="*">Home</Route>
</Switch>

It forces the router to pick only one of the routes. Without this component multiple matches are possible. Like in the example above, if there is no <Switch> the "Home" string will be rendered no mather what because * matches every route.

Base

<Base path="/my/app" />

It specifies the root of your application. If you deploy you code at specific path you have to either use this component or configureRouter to tell Navigo where to start from.

Prop type required Description
path string yes The root of your application.

NotFound

<NotFound>I'm 404 page.</NotFound>

It renders its content in case of a no match is found.

Redirect

<Redirect path="/a/new/place" />

It indirectly calls the navigate method of the router. Checkout redirecting example below.

Prop type required Description
path string yes The path where you want to go to.

Hooks

useNavigo

useNavigo is a hook that gives you access to the Navigo context. The main role of the context is to pass a Match object. It gives you access to the matched URL, URL and GET parameters. For example:

import { Route, useNavigo } from "navigo-react";

function User() {
  const { match } = useNavigo();

  return (
    <p>
      {match.params.action} user with id {match.data.id}
    </p>
  );
}

export default function App() {
  return (
    <>
      <a href="/user/xxx?action=save" data-navigo>
        Click me
      </a>
      <Route path="/user/:id">
        <User />
      </Route>
    </>
  );
}

The Navigo context also gives you access to key-value paris that we send via the router lifecycle functions. Check out this example Get data required by a Route.

useLocation

useLocation gives you a Match object that represents the current URL of the browser.

const match = useLocation();

Other functions

configureRouter

configureRouter could be used outside React and its purpose is to set the base root path of the router. Same as <Base> component.

configureRouter('/my/app');

reset

Calling this function means flushing all the registered routes.

getRouter

It gives you access to the Navigo router. Mostly you'll be using navigate and navigateByName functions. For example:

getRouter().navigate('/users/list');

Examples

Basic example

import { Switch, Route } from "navigo-react";

export default function App() {
  return (
    <>
      <nav>
        <a href="/" data-navigo>Home</a>
        <a href="/package" data-navigo>Package</a>
      </nav>
      <Switch>
        <Route path="/package">
          <ul>
            <li>Size: ~15KB</li>
            <li>Dependencies: no</li>
            <li>
              Documentation: <a href="https://github.com/krasimir/navigo-react">here</a>
            </li>
          </ul>
        </Route>
        <Route path="/">
          NavigoReact is a router for React applications based on Navigo project.
        </Route>
      </Switch>
    </>
  );
}

https://codesandbox.io/s/navigo-react-example-w9l1d

Accessing URL and GET parameters

import { Route, useNavigo } from "navigo-react";

function User() {
  const { match } = useNavigo();

  return (
    <p>
      {match.params.action} user with id {match.data.id}
    </p>
  );
}

export default function App() {
  return (
    <>
      <a href="/user/xxx?action=save" data-navigo>
        Click me
      </a>
      <Route path="/user/:id">
        <User />
      </Route>
    </>
  );
}

https://codesandbox.io/s/navigo-url-and-get-parameters-5few6

Redirecting

import { Route, Switch, Redirect } from "navigo-react";

export default function App() {
  return (
    <>
      <nav>
        <a href="/user" data-navigo>
          View user
        </a>
      </nav>
      <Switch>
        <Route path="/user">
          <Redirect path="/foobar" />
        </Route>
        <Route path="/foobar">Hey user!</Route>
      </Switch>
    </>
  );
}

https://codesandbox.io/s/navigo-redirecting-cxzbb

Get data required by a Route

import { Route, useNavigo } from "navigo-react";

function Print() {
  const { pic } = useNavigo();

  if (pic === null) {
    return <p>Loading ...</p>;
  }
  return <img src={pic} width="200" />;
}

export default function App() {
  async function before({ render, done }) {
    render({ pic: null });
    const res = await (
      await fetch("https://api.thecatapi.com/v1/images/search")
    ).json();
    render({ pic: res[0].url });
    done();
  }
  return (
    <>
      <nav>
        <a href="/cat" data-navigo>
          Get a cat fact
        </a>
      </nav>
      <Route path="/cat" before={before}>
        <Print />
      </Route>
    </>
  );
}

https://codesandbox.io/s/navigo-before-lifecycle-function-hgeld

Block opening a route

The user can't go to /user route.

import { Route } from "navigo-react";

export default function App() {
  const before = ({ done }) => {
    done(false);
  };

  return (
    <>
      <nav>
        <a href="/user" data-navigo>
          Access user
        </a>
      </nav>
      <Route path="/user" before={before}>
        Hey user!!!
      </Route>
    </>
  );
}

https://codesandbox.io/s/navigo-block-routing-e2qvw

Handling transitions

import { Route, Switch, useNavigo } from "navigo-react";

const delay = (time) => new Promise((done) => setTimeout(done, time));

const leaveHook = async ({ render, done }) => {
  render({ leaving: true });
  await delay(900);
  done();
};

function Card({ children, bgColor }) {
  const { leaving } = useNavigo();
  const animation = `${
    leaving ? "out" : "in"
  } 1000ms cubic-bezier(1, -0.28, 0.28, 1.49)`;

  return (
    <div
      className={`card ${leaving ? "leaving" : ""}`}
      style={{ backgroundColor: bgColor, animation }}
    >
      <p>{children}</p>
    </div>
  );
}

export default function App() {
  return (
    <>
      <Switch>
        <Route path="/card-two" leave={leaveHook}>
          <Card bgColor="#254c6a">
            Card #2.
            <br />
            <a href="/" data-navigo>
              Click here
            </a>{" "}
            to go back
          </Card>
        </Route>
        <Route path="/" leave={leaveHook}>
          <Card bgColor="#1f431f">
            Welcome to the transition example.{" "}
            <a href="/card-two" data-navigo>
              Click here
            </a>{" "}
            to open the other card.
          </Card>
        </Route>
      </Switch>
    </>
  );
}

https://codesandbox.io/s/navigo-handling-transitions-ipprc

navigo-react's People

Contributors

krasimir avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

navigo-react's Issues

Active class by default

How would I go adding an active class while using without writing custom JS?

<a href={'/crm/'+ans.machine} data-navigo>hep

Opening in a new tab

Doesnt open in a new tag with CMD click. Fixed in navigo, possible to get here also?

API alternative

Hi there,
I've created navigo react version for my side project before I had a chance to see this one. For this I've followed well-known react-router API so usage looks like this:

<NavigoRouter>
    <NavigoSwitch>
      <NavigoRoute path="/" component={LoginPage} />
      <NavigoRedirect to={'/'} />
    </NavigoSwitch>
</NavigoRouter>

Components can access router instance via useRouter hook, rendered routes have Match in their props and similarly to react-router it uses <Link to="/page">Page</Link> for navigation.

Would you be interested to consider this API? I can publish repo so you can have a look if you're interested

Switch inside Switch causes full refresh

We are looking for a structure with Switches inside Switches.

This causes a refresh of the whole app.

Is there a better way at going at this instead of making a full re-build of the app?

Main routes.

Class2

subroutes

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.