1.0.0-alpha.12 • Published 4 years ago

react-suspense-router v1.0.0-alpha.12

Weekly downloads
21
License
MIT
Repository
github
Last release
4 years ago

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

1.0.0-alpha.12

4 years ago

1.0.0-alpha.11

4 years ago

1.0.0-alpha.10

4 years ago

1.0.0-alpha.9

4 years ago

1.0.0-alpha.8

4 years ago

1.0.0-alpha.7

4 years ago

1.0.0-alpha.6

4 years ago

1.0.0-alpha.5

4 years ago

1.0.0-alpha.4

4 years ago

1.0.0-alpha.3

4 years ago

1.0.0-alpha.2

4 years ago

1.0.0-alpha.1

4 years ago

1.0.0-alpha.0

4 years ago

0.8.0

4 years ago

0.7.0

4 years ago

0.6.0

4 years ago

0.5.1

4 years ago

0.5.0

4 years ago

0.4.0

4 years ago

0.3.1

4 years ago

0.3.0

4 years ago

0.2.0

4 years ago

0.1.0

4 years ago

0.0.3

4 years ago

0.0.2

4 years ago

0.0.1

4 years ago

0.0.0

4 years ago