Giter Club home page Giter Club logo

meteor-react-mixin's Introduction

React Meteor

A Meteor Mixin for React

Getting Started

meteor add ccorcos:react-meteor

API

React.MeteorMixin

React.MeteorMixin allows you to tightly integrate Meteor with React.

This mixin with convert any props into reactive variables this.rprops so you can use them with getMeteorState for fine-grained reactivity of the state. If a props is an instance of ReactiveVar, then it will be passed into rprops as you might expect.

getMeteorState: {
  post() {
    return Posts.findOne(this.rprops.postId.get())
  }
}

Another convenience of this mixin is this.linkVar which is similar to this.linkState except it links an input to a ReactiveVar. This allows you to pass a reactive var as props to multiple components and both could change and reactively update to that ReactiveVar without having to handle all the piping in their common ancestor. linkVar will force a re-render even if the state or props don't change.

React.createClassFactory
  displayName: 'Header'
  mixins: [React.MeteorMixin, React.addons.PureRenderMixin]
  propTypes:
    searchVar: React.PropTypes.instanceOf(ReactiveVar).isRequired
  render: ->
    (div {},
      (input {type:'text', placeholder:'search', valueLink:@linkVar(@props.searchVar)})
    )

React.createClassFactory
  displayName: 'Results'
  mixins: [React.MeteorMixin, React.addons.PureRenderMixin]
  propTypes:
    searchVar: React.PropTypes.instanceOf(ReactiveVar).isRequired
  getMeteorState:
    postIds: -> 
      filter = new RegExp(@rprops.searchVar.get(), 'ig')
      posts = Posts.find({title: filter}, {sort: {name:1, date:-1}, fields: {_id: 1}}).fetch()
      _.pluck posts, '_id'
  render: ->  
    (div {},
      @state.postIds.map (postId) ->
        (Post {key: postId, postId: postId})
    )

React.createClassFactory
  displayName: 'Search'
  getInitialState: ->
    searchVar: new ReactiveVar('')
  render: ->
    (div {},
      (Header {searchVar: @state.searchVar})
      (Results {searchVar: @state.searchVar})
    )

Another helpful function is this.sessionVar which creates a ReactiveVar that binds to a Session variable. This way, the state of your app will persist across hot-code pushes and the state of your components will be maintained between mounts and unmounts.

React.createClassFactory
  displayName: 'Search'
  mixins: [React.MeteorMixin, React.addons.PureRenderMixin]
  getMeteorState:
    searchVar: -> @sessionVar('searchText')
  render: ->
    # ...

this.getSessionVars is a helper which uses this.sessionVar to bind Session variables to this.vars. This happens before getMeteorSubs and getMeteorState so you can use this.vars within those functions. This does not bind anything to this.state. The purpose of this is entirely to separate the global Session namespace from the component-level namespace. For example, here we separate the the 'home.postsLimit' Session variable from this.vars.postLimit.

  getSessionVars:
    postsLimit: 'home.postsLimit'

  getMeteorState:
    postIds: -> 
      posts = Posts.find({}, {sort:{name: 1, date:-1}, fields:{_id:1}}).fetch()
      _.pluck posts, '_id'
    canLoadMore: -> 
      @getMeteorState.postIds().length >= @vars.postsLimit.get()

  getMeteorSubs: ->
    sub = Meteor.subscribe('posts', @vars.postsLimit.get())
    return () -> sub.ready()

This mixin has getMeteorSubs which runs your subscriptions within an autorun so they will be automatically stopped once componentWillUnmount is called. You must return a reactive function that returns whether or not all subscriptions are ready. This will update the state variable this.state.subsReady and will block the component from re-rendering based on other state changes until subsReady is true. If you have multiple subscriptions, you should do something like this.

  getMeteorSubs: ->
    sub1 = Meteor.subscribe('post', postId)
    sub2 = Meteor.subscribe('user', userId)
    return () -> 
      a = sub1.ready()
      b = sub2.ready()
      return a and b

This also works well with meteorhacks:subs-manager or ccorcos:subs-cache.

subsCache = new SubsCache
  expireAter: 5
  cacheLimit: -1

# {clip}

  getMeteorSubs: ->
    subsCache.subscribe('post', postId)
    subsCache.subscribe('user', userId)
    # more subscriptions...
    subsCache.subscribe('comment', commentId)
    return () -> subsCache.ready() # returns ready if ALL are ready

React.createClassFactory

React.createClassFactory creates a class as you could expect, but also uses the display name to add the class to a global React.classes object and uses React.createFactory to add a factory of that class to a global React.factories object. This way, you can conveniently access you different classes from different files without polluting your global namespace. React.createClassFactory returns an array where the first element is the class and the second element is the factory of that class.

Factories are convenient if you don't want to use JSX and saves you from using React.createElement everywhere, especially for coffeescript. For example, in coffeescript, you might write like this.

{Item} = React.factories
{h2, p} = React.DOM

React.createClassFactory
  # ...
  render: -> 
    (Item {onClick: @props.onClick},
      (h2 {}, @state.post.title)
      (p {}, @state.post.user.username)
    )

React.renderBody

React.renderBody is a simple wrapper that renders to the body of the document. This works nicely with meteorhacks:flow-router.

FlowRouter.route('/', {
  action: function(params, queryParams) {
    Main = React.classes.Main
    React.renderBody(<Main/>)
  }
});
FlowRouter.route '/', 
  action: (params, queryParams) ->
    Main = React.factories.Main
    React.renderBody Main()

Examples

The best way to figure this stuff out is to check out the examples. You will also need to either clone my other repos parallel with this package (for the symlinks to work) or just remove the packages symlinks and download the packages from Atmosphere. I'll leave the symlinks though because it helps me debug.

To Do

  • fastRender (SSR)

meteor-react-mixin's People

Contributors

ccorcos avatar arunoda avatar

Stargazers

Gabriel Almeida avatar Justin C. avatar Gaurav avatar Feng Qiu avatar Tyler Hellner avatar pholmq avatar Nikolay Kolev avatar crapthings avatar Rhys Bartels-Waller avatar  avatar Bozhao avatar Philipp Muens avatar Andrejs M avatar

Watchers

James Cloos avatar  avatar  avatar

Forkers

arunoda

meteor-react-mixin's Issues

JavaScript examples instead of CofeeScript

This seems interesting but it will be nice to see some real JavaScript examples for those of us who want to stick with plain old JavaScript.
Is this possible or the package will work only with CofeeScript?
Thanks.

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.