• Stars
    star
    233
  • Rank 172,230 (Top 4 %)
  • Language
    JavaScript
  • Created over 6 years ago
  • Updated over 1 year ago

Reviews

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

Repository Details

react-streams

react-streams logo

Installation

Install both react-streams and rxjs

npm i react-streams rxjs

Build Status

CircleCI

Cypress Dashboard

About

react-streams enables you to stream from a source or props. The stream will pass through a pipe and new values will often be pushed through by plans.

Stream from sources

<Stream source={}/> - A component that subscribes to a source and streams values to children. The stream will pass through a pipe.

<Stream source={source$}>
  {values => <div>{values.message}</div>}
</Stream>

stream(source) - Creates a named component that subscribes to a source and streams values to children. The stream will pass through a pipe.

const MyStreamingComponent = stream(source$)

<MyStreamingComponent>
  {(values)=> <div>{values.message}</div>}
</MyStreamingComponent>

Stream from props

<StreamProps/> - A component that streams props changes to children. Changes to props will pass through the pipe and can be updated by plans.

<StreamProps message={message}>
  {values => <div>{values.message}</div>}
</StreamProps>

streamProps() - Create a named component that streams props changes to children. Changes to props will pass through the pipe and can be updated by plans.

const MyStreamingPropsComponent = streamProps()

<MyStreamingComponent message={message}>
  {(values)=> <div>{values.message}</div>}
</MyStreamingComponent>

Stream through pipe

pipe is any operator (or piped combination of operators) that you want to act on your stream. Pipes can be simple mappings or complex ajax requests with timing as long as they return a function that returns an object which matches the children's arguments.

<StreamProps
  message={message}
  pipe={map(({ message }) => message + "!")}
>
  {values => <div>{values.message}</div>}
</StreamProps>

Make a plan to update

plan is a function that can be observed.

const update = plan()

from(update).subscribe(value => console.log(value))

update("Hello") //logs "Hello"
update("Friends") //logs "Friends"

Examples

Enough chit-chat, time for examples!

Play with Examples at codesandbox.io

<Stream/>

Demo here

import React from "react"
import { Stream } from "react-streams"
import { of, pipe } from "rxjs"
import { delay, startWith } from "rxjs/operators"

const startWithAndDelay = (message, time) =>
  pipe(
    delay(time),
    startWith({ message })
  )

const message$ = of({ message: "Hello" })

export default () => (
  <div>
    <h2>Stream as a Component</h2>
    <Stream
      source={message$}
      pipe={startWithAndDelay("Wait...", 500)}
    >
      {({ message }) => <div>{message}</div>}
    </Stream>
    <Stream
      source={message$}
      pipe={startWithAndDelay("Wait longer...", 3000)}
    >
      {({ message }) => <div>{message}</div>}
    </Stream>
  </div>
)

stream

Demo here

import React from "react"
import { stream } from "react-streams"
import { interval } from "rxjs"
import { map } from "rxjs/operators"

const count$ = interval(250).pipe(
  map(count => ({ count }))
)

const Counter = stream(count$)

export default () => (
  <div>
    <h2>Subscribe to a Stream</h2>
    <Counter>
      {({ count }) => <div>{count}</div>}
    </Counter>
  </div>
)

pipe

Demo here

import React from "react"
import { stream } from "react-streams"
import { of } from "rxjs"
import { map } from "rxjs/operators"

const stream$ = of({ greeting: "Hello", name: "world" })

const mapToMessage = map(({ greeting, name }) => ({
  message: `${greeting}, ${name}!`
}))

const Greeting = stream(stream$, mapToMessage)

export default () => (
  <div>
    <h2>Pipe Stream Values</h2>
    <Greeting>
      {({ message }) => <div>{message}</div>}
    </Greeting>
  </div>
)

streamProps

Demo here

import React from "react"
import { streamProps } from "react-streams"
import { map } from "rxjs/operators"

const mapGreeting = map(({ greeting, name }) => ({
  message: `${greeting}, ${name}!`
}))

const HelloWorld = streamProps(mapGreeting)

export default () => (
  <div>
    <h2>Stream Props to Children</h2>
    <HelloWorld greeting="Hello" name="world">
      {({ message }) => <div>{message}</div>}
    </HelloWorld>
    <HelloWorld greeting="Bonjour" name="John">
      {({ message }) => <div>{message}</div>}
    </HelloWorld>
  </div>
)

Ajax

Demo here

import React from "react"
import { streamProps } from "react-streams"
import { pipe } from "rxjs"
import { ajax } from "rxjs/ajax"
import {
  pluck,
  switchMap,
  startWith
} from "rxjs/operators"

const getTodo = pipe(
  switchMap(({ url, id }) => ajax(`${url}/${id}`)),
  pluck("response")
)

const Todo = streamProps(getTodo)

const url = process.env.DEV
  ? "/api/todos"
  : "https://dandelion-bonsai.glitch.me/todos"

export default () => (
  <div>
    <h2>Ajax Demo</h2>
    <Todo url={url} id={2}>
      {({ text, id }) => (
        <div>
          {id}. {text}
        </div>
      )}
    </Todo>
    <Todo url={url} id={3}>
      {({ text, id }) => (
        <div>
          {id}. {text}
        </div>
      )}
    </Todo>
  </div>
)

Nested Streams

Demo here

import React from "react"
import { Stream, StreamProps } from "react-streams"
import { map, filter } from "rxjs/operators"
import { interval } from "rxjs"

const count$ = interval(1000).pipe(
  map(count => ({ count }))
)

const odds = filter(({ count }) => count % 2)
const evens = filter(({ count }) => !(count % 2))

export default () => (
  <Stream source={count$}>
    {({ count }) => (
      <div style={{ padding: "2rem" }}>
        <h2>
          Stream with Nested StreamProps Components
        </h2>
        <StreamProps count={count}>
          {({ count }) => <div>No filter: {count}</div>}
        </StreamProps>
        <StreamProps count={count} pipe={odds}>
          {({ count }) => <div>Odds: {count}</div>}
        </StreamProps>
        <StreamProps count={count} pipe={evens}>
          {({ count }) => <div>Evens: {count}</div>}
        </StreamProps>
      </div>
    )}
  </Stream>
)

Create a plan

Demo here

import React from "react"
import { StreamProps, plan } from "react-streams"
import { map, pluck } from "rxjs/operators"

const onChange = plan(
  pluck("target", "value"),
  map(message => ({ message }))
)

export default () => (
  <div>
    <h2>Update a Stream with Plans</h2>
    <StreamProps message="Hello" plans={{ onChange }}>
      {({ message, onChange }) => (
        <div>
          <input
            id="input"
            type="text"
            onChange={onChange}
          />
          <div id="message">{message}</div>
        </div>
      )}
    </StreamProps>
  </div>
)

scanPlans

Demo here

import React from "react"
import {
  scanPlans,
  plan,
  streamProps
} from "react-streams"
import { pipe } from "rxjs"
import { ajax } from "rxjs/ajax"
import {
  debounceTime,
  distinctUntilChanged,
  map,
  pluck
} from "rxjs/operators"

const handleInput = pipe(
  pluck("target", "value"),
  debounceTime(250),
  distinctUntilChanged(),
  /**
   * map to a fn which returns an object, fn, or Observable (which returns an
   * object, fn, or Observable)
   */
  map(term => props => {
    if (term.length < 2) return { people: [], term: "" }
    return ajax(
      `${props.url}?username_like=${term}`
    ).pipe(
      pluck("response"),
      map(people => ({
        term,
        people: people.slice(0, 10)
      }))
    )
  })
)

const Typeahead = streamProps(
  scanPlans({ onChange: plan(handleInput) })
)

const url = process.env.DEV
  ? "/api/people"
  : "https://dandelion-bonsai.glitch.me/people"

export default () => (
  <Typeahead url={url} people={[]}>
    {({ term, people, onChange }) => (
      <div>
        <h2>Search a username: {term}</h2>
        <input
          type="text"
          onChange={onChange}
          placeholder="Type to seach"
          autoFocus
        />
        <ul>
          {people.map(person => (
            <li
              key={person.id}
              style={{ height: "25px" }}
            >
              <span>{person.username}</span>
              <img
                style={{ height: "100%" }}
                src={person.avatar}
                alt={person.username}
              />
            </li>
          ))}
        </ul>
      </div>
    )}
  </Typeahead>
)

Counter Demo

Demo here

import React from "react"
import {
  scanPlans,
  plan,
  streamProps
} from "react-streams"
import { map } from "rxjs/operators"

const onInc = plan(
  map(() => state => ({ count: state.count + 2 }))
)
const onDec = plan(
  map(() => state => ({ count: state.count - 2 }))
)
const onReset = plan(map(() => state => ({ count: 4 })))

const Counter = streamProps(
  scanPlans({ onInc, onDec, onReset })
)

export default () => (
  <Counter count={4}>
    {({ count, onInc, onDec, onReset }) => (
      <div>
        <button
          id="dec"
          onClick={onDec}
          aria-label="decrement"
        >
          -
        </button>
        <span id="count" aria-label="count">
          {count}
        </span>
        <button
          id="inc"
          onClick={onInc}
          aria-label="increment"
        >
          +
        </button>
        <button onClick={onReset} aria-label="reset">
          Reset
        </button>
      </div>
    )}
  </Counter>
)

More Repositories

1

kit

Script Kit. Automate Anything.
TypeScript
3,453
star
2

angularjs-plugin

AngularJS features for the Intellij Platform (WebStorm, RubyMine, Intellij, etc)
Java
282
star
3

angular-resolve

A simple AngularJS project to demonstrate the "resolve" feature of routing
JavaScript
130
star
4

rx-handler

A simple function for handling events with streams
TypeScript
66
star
5

intro-to-angular2

TypeScript
55
star
6

kitapp

TypeScript
49
star
7

swapi-json-server

JavaScript
44
star
8

next-mdx-blog

JavaScript
38
star
9

open-source-plugins

Open-source plugins for IntelliJ
Java
37
star
10

speed-run

JavaScript
36
star
11

dotfiles

29
star
12

johnlindquist.com-deprecated

a place to drop demo code from johnlindquist.com
ActionScript
29
star
13

rxjs-in-angular2

JavaScript
28
star
14

automatoes.com

JavaScript
26
star
15

vue-typescript-simple

Vue
26
star
16

hackernuxt

Vue
25
star
17

Darkerula

A bit darker Darcula
Java
20
star
18

egghead-nuxt

Vue
18
star
19

johnlindquist.com

CSS
17
star
20

angular2-workshop

Egghead.io - Angular 2 Workshop
TypeScript
17
star
21

ng-hackathon-starter

An Angular 2 starter project for the ng-hackathon
JavaScript
16
star
22

vue-streams

Simple Streams for Vue
TypeScript
14
star
23

top-level-tools

top-level tools for ActionScript 3
ActionScript
13
star
24

angular-2-hello-world

An Angular 2 starter project for dev and production builds.
TypeScript
9
star
25

angular2-static-files-bundled

JavaScript
8
star
26

rxjs-operator-lessons

JavaScript
8
star
27

node-sheets

JavaScript
8
star
28

FDTThemeDesigner

ActionScript
8
star
29

luna

Luna: The Lua EventDisptacher
Lua
8
star
30

chrome-extension-lessons

JavaScript
7
star
31

angular-2-quickstart

a "checkout and go" repo for angular 2
JavaScript
7
star
32

todos-api

JavaScript
7
star
33

vue-rx-demos

Vue
6
star
34

flight-demos

Demos of the Flight Framework
ActionScript
6
star
35

angular2-lessons

Angular 2 Lessons
TypeScript
6
star
36

angular2-workshop-resources

Egghead.io - Angular 2 Workshop Resources
HTML
6
star
37

SimpleServer

JavaScript
6
star
38

has-bad-ideas

JavaScript
6
star
39

proxy-presentation

JavaScript
5
star
40

twimages

JavaScript
5
star
41

nuxt-typescript

Vue
5
star
42

node-lessons

JavaScript
5
star
43

netlify-puppeteer-template

JavaScript
5
star
44

svg-to-pdf

JavaScript
5
star
45

ElectroServerProject

An idea for my FlashBelt app
ActionScript
5
star
46

streamer-mode

CSS
5
star
47

kit-ai-conversation

TypeScript
4
star
48

ngrx-examples

TypeScript
4
star
49

compose-callback-workshop

JavaScript
4
star
50

FlashBelt

a workspace with FlashBelt stuff
ActionScript
4
star
51

next-lessons

JavaScript
4
star
52

TopTenTips

the outline of the top ten tips presentation
JavaScript
4
star
53

AsyncCommandTutorial

JavaScript
4
star
54

use-gsap

TypeScript
4
star
55

twitter-search

angular twitter search demo
4
star
56

crafting-functions

JavaScript
4
star
57

angular-summit-workshop

workshop instructions
3
star
58

people-api-lessons

JavaScript
3
star
59

react-rxjs-lessons

JavaScript
3
star
60

AngularJSTopTenTips

My "slides" for my talk
JavaScript
3
star
61

angular2-workshop-old

JavaScript
3
star
62

ShortcutHero

3
star
63

vercel-swapi-json-server

JavaScript
3
star
64

rxjs-training

Created with CodeSandbox
JavaScript
3
star
65

EggheadAngularWorkshop

The workshop files for the Egghead Angular 1.x workshop
JavaScript
3
star
66

automatoes.com-jekyll

a community of people who ❤️ automation
Ruby
3
star
67

maggie-kit

Kit Environment
TypeScript
3
star
68

angular-routing

a demonstration of routing in AngularJS
JavaScript
3
star
69

simple-contacts-app

TypeScript
3
star
70

netlify-function-template

JavaScript
3
star
71

DesignPatternsForDummies

The source code for my "Design Patterns for Dummies" presentation. Switch branches from the menu above to view the different patterns.
ActionScript
3
star
72

angular-presentation

Threw this together last night to play around with the idea of a presentation using angular
JavaScript
3
star
73

fieldofmemes

JavaScript
3
star
74

github-workflow-playground

Shell
2
star
75

swapi-graphql-server

JavaScript
2
star
76

globals

JavaScript
2
star
77

oreilly-article

Example code for "Building REST APIs with PyCharm in Just a Few Lines of Code" article
Python
2
star
78

lesson-generator

JavaScript
2
star
79

vue-rx-lessons

HTML
2
star
80

flight-core

Core library for ActionScript and MXML development, including Binding, Collections and several data types
ActionScript
2
star
81

alfred-twitter-likes

JavaScript
2
star
82

kit-extension

TypeScript
2
star
83

install-kit

JavaScript
2
star
84

cac-lessons

JavaScript
2
star
85

angular2-starter

JavaScript
2
star
86

midjourney

2
star
87

angular2-minimal

HTML
2
star
88

gyg-downloader

JavaScript
2
star
89

kit-internal

TypeScript
2
star
90

react-playground

JavaScript
2
star
91

angular-sharing-data-between-controllers

simple app showing how to share data from a service
2
star
92

todo-graphql

JavaScript
2
star
93

anki-data

JavaScript
1
star
94

rxjs-react-todo

JavaScript
1
star
95

postcss-lessons

JavaScript
1
star
96

anki

JavaScript
1
star
97

uFlash

uFlash projects
ActionScript
1
star
98

music-viz

JavaScript
1
star
99

vue-rx-bmi

Vue
1
star
100

kenv

JavaScript
1
star