Git Product home page Git Product logo

react-hydrate's Introduction

react-hydrate

Generic data fetching and SSR hydration pattern for React.

js-standard-style

Features & Goals

  1. Co-locate data dependencies with your components
  2. Supports infinitely nested loaders
  3. Fetches requested data on the server and hydrates on the client for a fast startup
  4. Wraps components so users can easily define loading states for components
  5. Routing agnostic. Works with react-router v4.
  6. Lightweight ~1.9kb

Related: react-hydrate-link - prefetch data for your next route using react-router v4.

Usage

Defining components

/**
 * Projects.js
 */
import api from 'my-api'
import { hydrate } from 'react-hydrate'
import Project from './Project.js'

export default hydrate(
  /**
   * dataLoader receives component props
   * and any state already in the store
   */
  (props, state) => {
    return api.fetchProjects().then(projects => {
      return {
        projects: projects
      }
    })
  },
  /**
   * mapStateToProps receives the
   * loaded data via `state` and any
   * component props.
   *
   * You should return `false` here if 
   * the data needed is not yet availabe.
   * If a falsy value is returned, it
   * tells the library that the loader
   * hasn't been run yet or hasn't
   * yet resolved.
   */
  (state, props) => {
    return state.projects ? {
      projects: state.projects
    } : false
  }
)(({ loading, data, ...inheritedProps }) => {
  /**
   * Component is always passed a loading
   * prop that represents the status of their
   * dataLoader function
   */
  return loading ? (
    <div>Loading data...</div>
  ) : (
    data.projects.map(project => <Project {...project} key={project.slug}>)
  )
})
/**
 * App.js
 */
import React from 'react'
import Projects from './Projects.js'

export default props => (
  <div>
    <Projects />
  </div>
)

Creating root app

import React from 'react'
import { render } from 'react-dom'
import { BrowserRouter as Router } from 'react-router-dom'
import { Tap } from 'react-hydrate'
import App from './App'

render((
  <Router>
    <Tap hydrate={window.__hydrate || null}>
      <App />
    </Tap>
  </Router>
), document.getElementById('root'))

Server

import React from 'react'
import { renderToString } from 'react-dom/server'
import { StaticRouter: Router } from 'react-router'
import { Tap, createStore } from 'react-hydrate'
import { asyncRender } from 'react-hydrate/dist/server'
import App from './App.js'

app.use((req, res) => {
  const ctx = {}
  const store = createStore({})

  const Root = (
    <Router location={req.url} context={ctx}>
      <Tap hydrate={store}>
        <App />
      </Tap>
    </Router>
  )

  asyncRender(Root).then(() => {
    const state = store.getState()
    const content = renderToString(Root)

    if (ctx.url) {
      res.writeHead(302, {
        Location: ctx.url
      })
      res.end()
    } else {
      res.send(`
        <!DOCTYPE html>
        <html>
          <head></head>
          <body>
            ${content}
            <script>
              window.__hydrate = ${JSON.stringify(state)}
            </script>
            <script src="/index.js"></script>
          </body>
        </html>
      `)
      res.end()
      store.clearState()
    }
  })
})

Dependencies

MIT License

react-hydrate's People

Stargazers

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

Watchers

 avatar

Forkers

archerbg

react-hydrate's Issues

Force fetch option

Would be good to add an option that would force a re-fetch and cache update. This could be determined by props if I allowed a function that returned an object as the options param.

Error prop?

Might want to pass an error down if one occurs, ensuring the traversal continues.

Support for dynamic nested, hydratable components?

Does this support nested, hydratable components, where the nesting is dynamic? For example:

  1. You have a top-level component that has a dataLoader function and thus loads data asynchronously. However, whilst that asychronous activity is taking place, it renders some sort of activity indicator.
  2. When the asynchronous activity finishes, the activity indicator is replaced with another component. However, that component also has its own dataLoader function, which kicks off its own asynchronous data load.

Put differently, imagine that in the example you have in your README, both the Projects and the Project component are wrapped with hydrate and have a dataLoader function. On the server side, I need to wait for all of this asynchronous activity to finish before I can send a response back to the client. Does react-hydrate support this scenario?

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.