npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-suspense-router

v1.0.0-alpha.12

Published

React Router for React Suspense and Render-as-You-Fetch

Downloads

28

Readme

react-suspense-router

Build Status npm version bundle size

React Router for React Suspense and Render-as-You-Fetch

Introduction

The new Render-as-You-Fetch pattern is mind-blowing.

This is an experimental library that combines react-router and some other libraries. You can get the benefit of Render-as-You-Fetch out of the box.

Install

yarn add react-suspense-router

Usage

App.tsx

import React, { Suspense } from 'react';

import { BrowserRouter } from 'react-suspense-router';

import Nav from './Nav';
import MyRoutes from './MyRoutes';

const App: React.FC = () => (
  <BrowserRouter timeout={1000}>
    <Nav />
    <Suspense fallback={<div>Loading...</div>}>
      <MyRoutes />
    </Suspense>
  </BrowserRouter>
);

export default App;

Nav.tsx

import React from 'react';

import { Link, useLocationPending } from 'react-suspense-router';

const Nav: React.FC = () => {
  const isPending = useLocationPending();
  return (
    <div>
      <div style={{ position: 'absolute', top: 0 }}>{isPending && 'Pending...'}</div>
      <ul style={{ marginTop: 20 }}>
        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/user/1">User 1</Link>
        </li>
        <li>
          <Link to="/user/2">User 2</Link>
        </li>
      </ul>
    </div>
  );
};

export default Nav;

Routes.tsx

import React from 'react';

import { Route, Routes, FetchDataLazy } from 'react-suspense-router';

const Index = React.lazy(() => import('./pages/Index'));
const User = React.lazy(() => import('./pages/User'));
const fetchUserData = FetchDataLazy(() => import('./pages/User.data'));

const MyRoutes: React.FC = () => (
  <Routes>
    <Route exact path="/">
      <Index />
    </Route>
    <Route path="/user/:uid" fetchData={fetchUserData}>
      <User />
    </Route>
  </Routes>
);

export default MyRoutes;

pages/Index.tsx

import React from 'react';

const Index: React.FC = () => (
  <div>
    <h1>Index</h1>
    <p>Hello World</p>
  </div>
);

export default Index;

pages/User.tsx

import React from 'react';

import { useParams, useRouteData } from 'react-suspense-router';

import { UserData } from './User.data';

const FirstName: React.FC = React.memo(() => {
  const userData = useRouteData() as UserData;
  return (
    <div>
      <h2>First Name</h2>
      <div>{userData.data.first_name}, random={Math.random()}</div>
    </div>
  );
});

const User: React.FC = () => {
  const { uid } = useParams();
  return (
    <div>
      <h1>User</h1>
      <div>uid: {uid}, random={Math.random()}</div>
      <FirstName />
    </div>
  );
};

export default User;

pages/User.data.ts

import { Match } from 'react-suspense-router';

export type UserData = {
  data: {
    id: number;
    email: string;
    first_name: string;
    last_name: string;
    avatar: string;
  };
};

const fetchUserData = async (match: Match) => {
  const userId = match.params.uid;
  const response = await fetch(`https://reqres.in/api/users/${userId}`);
  const data = await response.json();
  return data as UserData;
};

export default fetchUserData;

API

Routes

Routes for Suspense Render-as-You-Fetch

Its usage is the same with react-router, except that Route accepts fetchData prop. Specify a function created by FetchData or FetchDataLazy.

Examples

import { Routes, Route } from 'react-suspense-router';

const MyRoutes = () => (
  <Routes>
    <Route path="/" element={<Index />} />
    <Route path="/double/:number" element={<Double />} fetchData={fetchDouble} />
  </Routes>
);

useRoutes

useRoutes for Suspense Render-as-You-Fetch

Its usage is the same with react-router, except that Route accepts fetchData prop. Specify a function created by FetchData or FetchDataLazy.

FetchData

FetchData

This will wrap an async function and create fetchData that canbe passed to fetchData prop in .

Examples

import { FetchData, Route } from 'react-suspense-router';

const fetchDouble = FetchData(async (match) => {
  await sleep(1000);
  return { result: match.params.number * 2 };
});

<Route path="..." element={...} fetchData={fetchDouble} />

FetchDataLazy

FetchDataLazy

This is lazy loading version of FetchData. It will be used like React.lazy, but for route data.

Examples

import { FetchDataLazy, Route } from 'react-suspense-router';

const fetchUserData = FetchDataLazy(() => import('./pages/User.data'));

<Route path="..." element={...} fetchData={fetchUserData} />

useRouteData

useRouteData hook

This will return route data in components inside a route. It utilizes proxy-based tracking by React Tracked.

Examples

import { useRouteData } from 'react-suspense-fetch';

const FirstName = () => {
  const userData = useRouteData();
  return <div>userData.firstName</div>
};

useRouteDataSelector

useRouteDataSelector hook

This will return route data in components inside a route. It takes a selector function. Use this if proxy-based tracking doesn't work.

Examples

import { useRouteDataSelector } from 'react-suspense-fetch';

const selectFirstName = data => data.firstName;
const FirstName = () => {
  const firstName = useRouteDataSelector(selectFirstName);
  return <div>firstName</div>
};

Examples

The examples folder contains working examples. You can run one of them with

PORT=8080 yarn run examples:01_minimal

and open http://localhost:8080 in your web browser.

You can also try them in codesandbox.io: 01 02 03