This package has been deprecated

Author message:

This package is not maintained. Use `@fleur/froute` instead.

@fleur/route-store-dom
TypeScript icon, indicating that this package has built-in type declarations

2.2.0 • Public • Published

@fleur/route-store-dom npm version travis minifiedgzip

fluxible-router inspired router for fleur

Features

  • API prefetching supported
  • Completely able to using in Server Side Rendering
  • Lazy loading supported without extra code transformer
  • URL builder

Usage overview

See more detail in todomvc example

//
// Router.ts
//
import { createRouteStore } from '@fleur/route-store-dom'

export const Router = createRouteStore({
  userShow: {
    path: '/user/:id',
    action: ({ executeOperation }, route) =>
      Promise.all([executeOperation(fetchUser, { id: route.param.id })]),
    handler: () => import('./routes/User'),
    meta: {
      noHeader: true,
    },
  },
})

//
// routes/UserShow.tsx
//
import { Link } from '@fleur/route-store-dom'
import { Router } from '../Router.ts'

// if you want to use route in class component,
// see packages/example-todomvc/src/routes/Index.tsx
export const UserShow = () => {
  const { routerContext, params } = useRoute()

  const { user } = useStore(getStore => ({
    user: getStore(UserStore).getUser(params.id),
  }))

  // Handling API side not found in render time
  if (!user) {
    routerContext.status = 404
    return <NotFound />
  }

  return (
    <div>
      {/* Link component and URL builder */}
      <Link href={Router.makePath('userShow', { id: params.id })}>
        {user.name}
      </Link>
    </div>
  )
}

//
// components/AppRoot.tsx
//
export const AppRoot = () => {
  const { route, error, routerContext } = useRoute()

  return (
    <div>
      {/* Handle not found*/}
      {!route && <div>Not Found</div>}

      {error && <div>500 Error</div>}

      {/* get .meta property from route.meta */}
      {route && !route.meta.noHeader && <header />}

      {/* mount Handler component here */}
      {route && route.handler && <route.Handler />}
    </div>
  )
}

//
// server.tsx
//
import Fleur from '@fleur/fleur'
import { navigateOp, createRouterContext } from '@fleur/route-store-dom'
import express from 'express'
import { Router } from './Router'
import { AppRoot } from './components/AppRoot'

const server = express()
const app = new Fleur({ stores: [RouteStore] })

server.use(async (req, res) => {
  const context = app.createContext()
  const routerContext = createRouterContext()

  // Route to handler.
  // It's executes API fetch and lazy component loading
  await context.executeOperation(navigateOp, {
    url: req.url,
  })

  const content = ReactDOMServer.renderToString(
    <FleurContext value={context}>
      <RouterContext value={routerContext}>
        <AppRoot />
      </RouterContext>
    </FleurContext>,
  )

  const rehydrated = JSON.stringify(context.dehydrate())

  res.status(routerContext.status)
  res
    .write('<!doctype html>')
    .write(<Html state={rehydrated} content={content} />)
    .end()
})

//
// client.tsx
//
import { AppRoot } from './components/AppRoot'
import { FleurContext } from '@fleur/react'
import { RouterProvider, restoreNavigateOp } from '@fleur/route-store-dom'

document.addEventListener('DOMContentLoaded', async () => {
  const state = JSON.parse(document.querySelector('#state').innerHTML)
  const context = app.createContext()

  context.rehydrate(state)

  // **IMPORTANT** It's required before rendering for fetching import()ed components!
  await context.executeOperation(restoreNavigateOp)

  ReactDOM.hydrate(
    <FleurContext value={context}>
      <RouterProvider>
        <App />
      </RouterProvider>
    </FleurContext>,
    document.querySelector('#react-root'),
  )
})

Readme

Keywords

none

Package Sidebar

Install

npm i @fleur/route-store-dom

Weekly Downloads

1

Version

2.2.0

License

MIT

Unpacked Size

28.3 kB

Total Files

30

Last publish

Collaborators

  • fsubal1102
  • geta6
  • hanakla
  • ragg