Preview of official React support

I might be wrong but my impression is that state should be reserved for keeping track of the state of your UI while data is simply data. Not sure why you’d couple the two together? Then again, I’ve never done React outside of the basic tutorials.

1 Like

I think that’s exactly what we are doing, by following the trends in future React development for the observe API, and popular packages like Parse. Also, AFAIK people who use Flux definitely don’t put their server-side data on this.state.

2 Likes

Okay. Got it now.
try to put this on the guide as well.
It’s worth mentioning it there.

3 Likes

@dgreensp we should write something up about this since people keep bringing it up.

Probably right next to this section: http://react-in-meteor.readthedocs.org/en/latest/meteor-data/#why-we-decided-to-ship-a-mixin

1 Like

Call for community React related packages to put in guide

Hi everyone who has been posting in this thread! I want to compile a list of useful React+Meteor projects that have popped up since the initial release of these packages, and add them to the guide so that people don’t have to read all of the github issues to find this stuff.

I’m going to go through the conversations on GitHub looking for those projects, but if you have others that I should mention, let me know!

While you’re planning what to include in the docs, could you consider adding a section on refactor paths between Blaze and React? Ideally, something along the lines of the following:

Blaze in Separate Files <==> React in Separate Files <==> Single File React
[HTML, CSS JS] <==> [JSX, JSS, JS] <==> JS(JSX, JSS)

I opened up another thread this morning which details some use cases as to why these kinds of refactor paths are useful/important. Hopefully it will generate some community discussion. But I suspect this may need some MDG guidance as well.

1 Like

Hi, I saw your thread over there. Let’s see what people say; if there is demand for more migration tools we can think about building them, but it looks like there are already some great community things about it, like the jsx-templating package here: https://atmospherejs.com/timbrandin/jsx-templating

I suspect the need for refactoring between different view layers will be very application or situation specific, so it might make sense to have people build their own tools for that.

What’s the difference between this and reactjs:react? I’ve just started using the latter with Webpack to integrate React, and nothing seems to be lacking yet.

How exactly do you mean about server-side data? Data from the server side (or something derived from it) pretty much has to go in the state of some component, even if that’s a controller-view that passes things from its state down via props.

I looked at the tutorials on this, I have to say I frankly don’t understand some things. I like how reactjs:react puts getMeteorState() in this.state because then you can track that with the lifecycle methods like componentWillUpdate(), shouldComponentUpdate(), etc. Why this package puts things in this.data instead (and calls forceUpdate() I assume?), I don’t understand. I’m sorry, I’m going to keep promoting reactjs:react unless I can see some kind of advantage to this package.

I’ve put the reactjs:react mixin into a setState infinite loop in certain edge cases. this.data eliminates that.

Using this.state may seem like a great idea but ideally you want your data coming from props. You should avoid this.state whenever possible (many times it’s not).

The best pattern with Meteor so far is to use the container pattern. Your FeedListContainer handles the subscription and mixin, sideloading the data from Meteor. It passes this.data into it’s only component FeedList as props. The container only has one job, gather data and push it down via props.

The FeedList component now knows nothing about how it’s getting it’s data. It’s basically a pure function that has params (props). It’s now very re-useable and easy to test (it just takes in props). FeedList can implement shouldComponentUpdate to cancel rendering on children.

FeedListContainer = React.createClass({
  mixins: [ReactMeteorData],

  getMeteorData: function() {
    var sub = Meteor.subscribe("feed");

    return {
      feedReady: sub.ready(),
      postItems: Posts.find({}, {sort: {createdAt: -1}}).fetch(),
    };
  },

  render() {
    return (
      <FeedList
        isReady={this.data.feedReady},
        postItems={this.data.postItems}
      />
    );
  }
});

and then the feed list…

FeedList = React.createClass({
  propTypes: {
    postItems: React.PropTypes.object,
    isReady: React.PropTypes.bool,
  },

  render() {
    if (!this.props.isReady) {
      return <LoadingSpinner />
    }

    return (
      <div className='FeedList-container'>
        {
          this.props.map(function(post) {
            return <Post postData={post} />
          })
        }
      </div>
    );
  }
});

[quote="jedwards, post:64, topic:6150"] How exactly do you mean about server-side data? [/quote]

I think @sashko was referring to Flux users who are loading serverside data are not using this.state in their component. Instead the component merely triggers an action (say and action called PRESSED_LOAD_MORE) and loads in data from the server. This data is stored in a Flux store (global state for a domain). The component just requests state from the Flux store on render and never touches setState (you could use setState to load the Flux data but you don’t have to).

this.state should really only (ideally) be used to keep track of transient state of a component… say which tab is open in a tab list, or what photo a gallery is indexed at… not the feed of post data. You can do this but it doesn’t scale well.

5 Likes

Hey, I think it’s totally legitimate to want that stuff in this.state. Before you start using reactjs:react again, let me suggest an alternative:

  1. Use the react-runtime package. This is the package that all Meteor packages and apps that use React should start depending on, so that you don’t end up shipping multiple versions of the React library. This package includes no mixins or anything else.
  2. Use the jsx package. We have put a lot more effort into making it stable on all platforms, and it will be maintained as part of Meteor core moving forward.
  3. Copy the mixin logic from reactjs:react into a new package - you could call it jedwards:get-meteor-state. Now, you can use the pattern you like.

With this approach, you will get all of the benefits of using mostly core Meteor packages which are guaranteed to be maintained into the far future, while not having to use react-meteor-data which you don’t like.

This is the reason we have published all of the parts of react separately - exactly so that you can pick or choose the parts you like.

4 Likes

Were the setState infinite loops triggered by the mixin itself or was your code doing Meteor work in shouldComponentUpdate, componentWillUpdate, or componentDidUpdate that inadvertently triggered a call to getMeteorState? I could imagine that if you need to respond to changes in transient state caused by the user, your code would accidentally get triggered by the getMeteorState changes as well…

Not all websites are social media feed lists. If that’s all you’ve worked on you might get used to some patterns that work well, but they don’t necessarily work well for other kinds of websites (for instance, I’ve used setState() with Immutables to improve performance in an interactive dashboard layout).

From the React website itself: setState(function|object nextState[, function callback])
“Merges nextState with the current state. This is the primary method you use to trigger UI updates from event handlers and server request callbacks.

And I know about this container pattern (React actually calls it the controller-view pattern) and use it often. But still, my controller-views are often using setState and passing down props from this.state instead of using forceUpdate or React.render.

If Flux patterns shun this dictum from the horse’s mouth, how to do they trigger UI updates? forceUpdate or React.render?

1 Like

My hesitation to use the jsx package is that I don’t like dealing with the package global vars and script load order in idiomatic meteor…or does the jsx package allow ES6 import?

I was talking about it as an alternative to reactjs:react which also doesn’t have support for modules.

Probably the latter… to be honest I can’t remember the exact details.


[quote="jedwards, post:68, topic:6150"] Not all websites are social media feed lists. If that's all you've worked on you might get used to some patterns that work well, but they don't necessarily work well for other kinds of websites (for instance, I've used setState() with Immutables to improve performance in an interactive dashboard layout). [/quote]

I think it would still work well with that kind of app though? I’ve used it in a dashboard interface with lots of widgets. However I think that the extra layer is a bit cumbersome though.


Sure. After re-reading my post I didn’t mean to come across as anti-state. What I meant is the state is stored in the store, not the component. To be honest I haven’t looked too hard into the inner workings of the different flux implementations but some that i’ve seen use setState and others forceRender after re-fetching (Alt uses getInitialState and returns the store typically… not too familiar with others).

I’ve been wanting to tinker with using an immutable lib with Meteor and a Flux lib and somehow get data from the subscription in a store and then save into the immutable when the data changes… However I haven’t got any farther than that. With the latency compensation it might be fairly easy to do this in the store (as opposed to async) or even a utils folder.

Sorry, it’s just the typical anxiety I have these days of “what? the way I’m doing things is bad practice?”

Immutable is kind of cool, but it’s a bit cumbersome to use, so I only use it when the performance benefits outweigh the cumbersomeness, though I’ve also used it at times to avoid needing to return a copy of the data from the stores (when not using Meteor, that is)

1 Like

@sashko @avital I’m not sure why I get this error:

Error: In template "board", call to `{{> React ... }}` missing `component` argument.

My code looks like this:

JavaScript:


MyComponent = React.createClass({
    mixins: [ReactMeteorData],
    render() {
        return (
            <div className={'famous-board-container '+this.props.board._id}></div>
        )
    },
    onComponentDidMount() {
        console.log('Mounted a React component.')
    }
})

HTML:

      {{> React component=MyComponent board=this }}

Ah, well, I found the workaround:

Template.blazeTemplateThatWillContainReact.onRendered(() => {
    React.render(MyComponent, this.$('.targetElement')[0])  
})

You need to pass in the component with a helper.