GithubHelp home page GithubHelp logo

aweary / react-context-emission Goto Github PK

View Code? Open in Web Editor NEW

This project forked from reacttraining/react-broadcast

0.0 2.0 0.0 24 KB

React context wrapper to safely provide props deeply in the component tree.

HTML 9.25% JavaScript 90.23% CSS 0.51%

react-context-emission's Introduction

React Context Emission

react-context-emission React context wrapper to safely provide props deeply in the component tree.

Installation

Using npm:

$ npm install --save react-context-emission

Then with a module bundler like webpack, use as you would anything else:

// using an ES6 transpiler, like babel
import { createContextEmitter, createContextSubscriber } from 'react-context-emission'

// not using an ES6 transpiler
const { createContextEmitter, createContextSubscriber } = require('react-context-emission')

The UMD build is also available on npmcdn:

<script src="https://npmcdn.com/react-context-emission/umd/react-context-emission.min.js"></script>

You can find the library on window.ReactContextEmission.

Motivation

Sometimes you have some state in a component you want to make available to any arbitrary descendant in the component tree. Passing props deeply gets cumbersome, recursively cloning is not very exciting, monkey-patching createElement is terrifying, and externalizing that state with another library requires you to bail out of React and decrease the reusability of your component.

:(

Context, however, seems like a great place to put that state. It's available arbitrarily deep in the tree and maintains React's encapsulated composability and reusability. It would be enough on its own, except that accessing the values on context is not reliable.

Any component in the tree that implements shouldComponentUpdate has no way of knowing if the values on context have changed. This means that a setState on a context providing component won't always cause a rerender of components deeper in the tree that need that state from context.

So, instead of using context as a place to store values, it can be used to provide a way to subscribe to the values, ensuring deep rerenders when the values change.

This library gives you a way to create components to do the provide/subscribe dance declaratively inside your app, providing state from up high to down low with ease.

Usage

First, a fair warning about using this a lot:

https://twitter.com/sebmarkbage/status/781371101708296192

Let's say you want to listen to the geo location and make that data available anywhere in the app.

import { createContextEmitter, createContextSubscriber } from 'react-context-emission'

const GeoEmitter = createContextEmitter('geo')
const GeoSubscriber = createContextSubscriber('geo')
// the string "geo" is the key used on context

// Here's the component that keeps the device's position in state
class GeoProvider extends React.Component {

  state = {
    geo: null
  }

  componentDidMount() {
    navigator.geolocation.watchPosition((geo) => {
      this.setState({ geo })
    })
  }

  render() {
    return (
      // render the Emitter
      <GeoEmitter value={this.state.geo}>
        {this.props.children}
      </GeoEmitter>
    )
  }

}

// Now, any arbitrary descendant of GeoProvider can access the geo
// information by rendering a GeoSubscriber, if the geo data changes
// and we're below a `shouldComponentUpdate` we'll still get an update
class SomeDeepComponent extends React.Component {
  render() {
    return (
      <GeoSubscriber>
        {(geo) => geo ? (
          <dl>
            <dt>latitude</dt>
            <dd>{geo.coords.latitude}</dd>
            <dt>longitude</dt>
            <dd>{geo.coords.longitude}</dd>
          </dl>
        ) : (
          <p>Getting geoposition...</p>
        )}
      </GeoSubscriber>
    )
  }
}

Some folks would prefer a higher order component that passes the geo props to a wrapped component instead of a render callback, that's pretty quick to implement:

const withGeo = (Component) => (
  (props) => (
    <GeoSubscriber>
      {(geo) => (
        <Component geo={geo} {...props}/>
      )}
    </GeoSubscriber>
  )
)

react-context-emission's People

Contributors

ryanflorence avatar

Watchers

 avatar  avatar

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.