• Stars
    star
    108
  • Rank 321,259 (Top 7 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created about 5 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

React utilities for working with APIs

react-zen

NPM

A collection of simple utilities for React

yarn add react-zen

What?

Currently, react-zen contains just two utilities:

  • createMirror(fetcher)
  • useSnapshot(handle)

Together, these two functions let you easily consume asynchronous data in your React components. For example, here's how you'd load and display data from a REST API:

import { Suspense } from 'react'
import { createMirror, useSnapshot } from 'react-zen'

// A mirror automatically fetches data as it is required, and purges it
// once it is no longer in use.
const api = createMirror(async url => {
  let response = await fetch(BaseURL+url)
  return response.json()
})

function Screen() {
  // useSnapshot returns your data, loading status, etc.
  let { data } = useSnapshot(api.key('/todos/1'))
  return <div><input checked={data.completed} /> {data.title}</div>
}

function App() {
  return (
    // Make sure to wrap your any component that use `useSnapshot()`
    // with a <Suspense> tag.
    <Suspense fallback={<div>Loading</div>}>
      <Screen />
    </Suspense>
  )
}

Of course, you'll also want to be able to refresh and update your data. Mirrors and snapshots both have a suite of methods to make this easy. You can see how this works at the live example:

See a full featured example at CodeSandbox

API

useSnapshot()

Returns a snapshot of the data specified by the given handle.

export function useSnapshot(
  handle: MirrorHandle,
): {
  data: Data
  key: Key

  /**
   * Set to true after `invalidate` has been called, and stays true until a
   * more recent version of the document is received.
   */
  invalidated: boolean

  /**
   * Indicates that a fetch is currently taking place.
   */
  pending: boolean

  /**
   * Starts as false, and becomes true once `data` is set for the first time.
   */
  primed: boolean

  /**
   * Marks this key's currently stored snapshot as invalid.
   *
   * If there's an active subscription, a new version of the data will be
   * fetched.
   */
  invalidate(): void

  /**
   * Stores the given data. If there is no subscription for it, then the data
   * will be immediately scheduled for purge.
   *
   * In the case a function is given, if this key has a non-empty snapshot,
   * then the updater callback will be called and the returned value will be
   * set as the current data. If the key's snapshot is empty or is not yet
   * primed, then an error will be thrown.
   *
   * This will not change the `pending` status of your data.
   */
  update(dataOrUpdater: Data | MirrorUpdaterCallback): void
}

createMirror()

Create a mirror of the data in some asynchronous source, where data is automatically fetched as required, and purged when no longer needed.

createMirror(fetch: (
  snapshot: Snapshot,
  context: Context
) => Promise<Data>)

Mirror

The object returned by createMirror().

interface Mirror {
  /**
   * Return a handle for the specified key, from which you can get
   * and subscribe to its value.
   */
  key(key: string): MirrorKeyHandle

  /**
   * Return a handle for the specified keys, from which you can get
   * and subscribe to all their values at once.
   */
  key(keys: string[]): MirrorKeyListHandle

  /**
   * Return a list of the keys currently stored in the mirror for the given
   * deps array.
   */
  knownKeys(): Key[]
}

MirrorHandle

As returned by mirror.key(key) and mirror.keys(keys)

interface MirrorHandle {
  key: Key

  /**
   * Returns a promise to a mirrored snapshot for this key.
   */
  get(): Promise<MirrorPrimedSnapshot<Data>>

  /**
   * Returns the latest snapshot for the given data.
   */
  getLatest(): MirrorSnapshot<Data>

  /**
   * Subscribe to updates to snapshots for the given key. Note that this will
   * not immediately emit a snapshot unless subscribing triggers a fetch, and
   * adds/updates a snapshot in the process.
   */
  subscribe(
    callback: MirrorSubscribeCallback<Data, Key>,
  ): MirrorUnsubscribeFunction

  /**
   * Marks this key's currently stored snapshot as invalid.
   *
   * If there's an active subscription, a new version of the data will be
   * fetched.
   */
  invalidate(): void

  /**
   * Stores the given data. If there is no subscription for it, then the data
   * will be immediately scheduled for purge.
   *
   * In the case a function is given, if this key has a non-empty snapshot,
   * then the updater callback will be called and the returned value will be
   * set as the current data. If the key's snapshot is empty or is not yet
   * primed, then an error will be thrown.
   *
   * This will not change the `pending` status of your data.
   */
  update(dataOrUpdater: Data | MirrorUpdaterCallback): void
}

Contributing / Plans

A number of undocumented placeholder functions currently exist, which throw an exception when called. PRs implementing theses would be very welcome. Functions include:

  • mirror.keys(), which should allow you to get/subscribe to a list of keys at once.
  • mirror.hydrateFromState(), which should allow serialized data to be passed from the server to the client.
  • mirror.purge(), which should allow all data within a mirror to be immediately purged.
  • handle.predictUpdate(), which should allow for optimistic updates to be recorded against a key.

A number of other features have already been implemented, but need documentation and testing. These include namespaces and extractState(), both of which would be useful for server side rendering.

Once mirror.keys() has been implemented, it should be possible to create a CollectionMirror, which allows you to subscribe to queries/collections as well as individual records.

On other feature that would go a long way to improving real world use would configurable strategies for fetching invalidated/initial data -- instead of just giving up after the first fetch, as currently happens. Alongside this, it may make sense to have the ability to command a fetch, as opposed to just marking data as invalidated and allowing fetch to happen automatically.

License

react-zen is MIT licensed.

More Repositories

1

create-react-blog

Start and deploy your own statically rendered blog with create-react-app
JavaScript
548
star
2

starter-kit

Project boilerplate using React, Redux and Uniloc
JavaScript
467
star
3

gulp-rev-replace

Rewrite occurences of filenames which have been renamed by gulp-rev
JavaScript
388
star
4

govern

Component-based state management for JavaScript.
TypeScript
266
star
5

react-pacomo

Automatic Namespacing for your React className props
JavaScript
193
star
6

javascript-cheatsheets

A collection of cheatsheets for JavaScript
HTML
177
star
7

webpack-black-triangle

A minimal webpack/ES6 project template with a spinning black triangle
JavaScript
166
star
8

memamug-client

Memamug helps you remember faces. Written with React, Maxim & Rails.
JavaScript
109
star
9

uniloc

Universal JavaScript Route Parsing and Generation
JavaScript
95
star
10

raw-react-part-1

Learn Raw React - No JSX, Flux, ES6, Webpack, ...
JavaScript
74
star
11

memamug-server

Memamug helps you remember faces. Written with React, Maxim & Rails
Ruby
68
star
12

use-codemirror

CodeMirror support for React
JavaScript
66
star
13

retil

The React Utility Library
TypeScript
46
star
14

maxim

Maxim provides a simple way to structure JavaScript applications, letting you focus on the parts that matter.
JavaScript
45
star
15

pacomo

A Method For Structuring Stylesheets in React-based Applications
42
star
16

cura-firebase-example

A React/Firebase starter with serverless SSR, routing and styled components.
JavaScript
29
star
17

reactjs.tokyo

Source for reactjs.tokyo. Built with universal-react-scripts and Firebase.
JavaScript
28
star
18

raw-react-part-2

Solution for Learn Raw React: Ridiculously Simple Forms
JavaScript
26
star
19

react-black-triangle

An opiniated React starter kit. Clone, follow the README, and have a working app in under two minutes.
JavaScript
26
star
20

sitepack

A JavaScript tool for building static web sites.
JavaScript
25
star
21

react-cx

Combine styles from CSS Modules with a `cx` prop.
JavaScript
24
star
22

react-base

Higher order component to handle merging callbacks, prefixing classnames and props passthrough.
JavaScript
21
star
23

raw-react-part-3

Learn Raw React - Routing
JavaScript
19
star
24

armo-breadboard

Themeable live coding for React.
JavaScript
16
star
25

popup-trigger

A helper for triggering popups on focus, hover, and selection.
TypeScript
15
star
26

memcord

Memcords let you pass Records as React props without breaking PureComponent.
TypeScript
14
star
27

mdx-loader

Webpack loader for MDX (i.e. JSX-infused Markdown) using mdx-it
JavaScript
14
star
28

react-typescript-firebase-navi

A starter kit to get you started faster than all the other starter kits 🚅🔥🚀🍒
TypeScript
13
star
29

vouch.chat

JavaScript
11
star
30

derby-i18n

i18n support for derby.js
JavaScript
10
star
31

numbat-ui

CSS
10
star
32

use-promised-state

A state hook for React that doesn't whinge if used once used after unmount.
JavaScript
9
star
33

react-controllers

Utilities for creating React controller components
TypeScript
9
star
34

react-c

An implementation of Pacomo, a system to help structure your React stylesheets.
JavaScript
9
star
35

universal-react-app

A server-rendered starter forked from create-react-app
JavaScript
8
star
36

use-sx

Composable styles for React
TypeScript
8
star
37

node-joyo-kanji

A list of the Joyo Kanji packaged for node.js
8
star
38

react-routing-library

Concurrent routing that grows with your app.
TypeScript
7
star
39

firebase-react-demo

A simple demo of adding Firebase Functions/Hosting to a Create React App project
JavaScript
6
star
40

react-elemap

A tool for transforming React elements.
JavaScript
5
star
41

react-armory-helpers

Packages that can used with ES6 `import` within React Armory guides
4
star
42

static-directory-loader

Copy files into your public directory with a webpack import
JavaScript
4
star
43

react-junctions

JavaScript
3
star
44

meteor-yaml

Meteor smart package for YAML parsing/generation
JavaScript
2
star
45

mdx-cra-demo

JavaScript
2
star
46

junctions-react-app

A demo project using Junctions in the structure generated by Create React App
JavaScript
2
star
47

react-base-control

Higher order component to manage control-related events and state.
JavaScript
2
star
48

numbat-ui-example

JavaScript
1
star
49

angular-deputy

Resources with associations, computed values and offline support for AngularJS
CoffeeScript
1
star
50

m-and-c-in-mvc-talk

CSS
1
star
51

now-cura

Now builder for Create Universal React App
TypeScript
1
star
52

junctions-tutorial

Companion repo for the Junctions tutorial
JavaScript
1
star
53

armo

React stuff
JavaScript
1
star
54

vouch-landing

A landing page built in 2 hours with React and Firebase
JavaScript
1
star