[Article] Data Loading In React: Four Techniques Compared

While talking with @joshowens the other day he pointed out that there are now many different approaches to data loading in React. So I thought I’d write up a quick comparison of four techniques:

  • getMeteorData
  • TrackerReact
  • React Komposer
  • My own React List Container

https://www.discovermeteor.com/blog/data-loading-react/

9 Likes

Thanks for the clarification. It’s hard to match the simplicity of React List Container.

Hey, nice work!

I think that I disagree about TrackerReact, I find it to be much more transparent and easy to build smart containers and pass props down to dumb components easily. I don’t really think the pattern is easier or harder because of TrackerReact. I think it is much more clear how it all works when you build one, though.

Sadly, the recent class I gave covered React Komposer and Tracker React, but not the React List container. I should try it soon for comparison.

2 Likes

The excellent Meteor Guide hasn’t yet been updated to cover React, but once it has I’m sure it’ll point out the best solution.

For those interested in MDG’s current line of thinking, take a look at the react-content branch of the Guide.

If someone wants to use MDG createContainer right now, here is a wrapper-helper from MDG module-todos-react. Works great.

As an addition to comparing all these 4 techniques, when you’re using MDG wrapper or React Komposer, it’s easy to switch from one tool to another and it’s more react reusable components approach.

2 Likes

That article talks about creating a ListsShowPage using createComponent and then using it via <ListsShowPage params={{id: '7'}}/>. But where is ListsShowPage defined? (createComponent doesn’t have/use ListsShowPage)

The docs are definitely still a work in progress. The example todos app they will be updated to match is here.

Lets imagine that it was list-show-page.js. Then anywhere else you can import and use it

import ListsShowPage from './list-show-page.js' 

// note we use export default there. So it is no matter how to name it
// when importing
// if you like you may import it with any other name like
// import MySuperContainer from './list-show-page.js'

render(<ListsShowPage params={{id: '7'}}/>, document.body);

@hwillson

It’s not clear to me, are they going to update the docs from the todos example (which doesn’t even reference createComponent) or the example from the docs?

@mrzafod

That’s how you reference ListsShowPage, I want to know how it’s defined. In your example it’s the contents of list-show-page.js. The docs have the following which doesn’t mention ListsShowPage:

import { Meteor } from 'meteor/meteor';
import { Lists } from '../../api/lists/lists.js';
import createContainer from 'meteor/react-meteor-data';
import ListsShow from '../pages/ListsShow.jsx';

export default createContainer({ params } => {
  const { id } = params;
  const todosHandle = Meteor.subscribe('todos.inList', id);
  const loading = !todosHandle.ready();
  const list = Lists.findOne(id);
  const listExists = !loading && !!list;
  return {
    loading,
    list,
    listExists,
    todos: listExists ? list.todos().fetch() : [],
  };
}, ListsShow);

So how do you go from that to <ListsShowPage params={{id: '7'}}/>?

Maybe @sashko can chime in…

I believe the plan is to update the docs from the example app - see the following comment at the bottom of react.md:

XXX: not putting in code samples here as they may change and I don’t want to have to remember to do it in two places.

(leads me to believe they’re focusing on code changes in the sample app first)

Yes, guess it is missed. But it is pretty clear from the text. So let me show full (I suppose) example

// lists-show-page.js
// --------------------------------------------------------------------------------
import { Meteor } from 'meteor/meteor';
import { Lists } from '../../api/lists/lists.js';
import createContainer from 'meteor/react-meteor-data';
import ListsShow from '../pages/ListsShow.jsx';

export default createContainer({ params } => {
  const { id } = params;
  const todosHandle = Meteor.subscribe('todos.inList', id);
  const loading = !todosHandle.ready();
  const list = Lists.findOne(id);
  const listExists = !loading && !!list;
  return {loading, list, listExists, todos: listExists ? list.todos().fetch() : []};
}, ListsShow);

// app.js
// --------------------------------------------------------------------------------
import {render} from 'react-dom';
import NoMatterHowYouNameMe  from './lists-show-page.js'

render(<NoMatterHowYouNameMe params={{id: '7'}}/>, document.body); 
1 Like

Yes, this is one of the reasons I (personally) want to switch to named exports, so instead of:

export default createContainer ...

import AnyNameYouWant from '...';

it would be:

export const ListsShowPage = createContainer ...

import { ListsShowPage } from '...';

I think the second is preferable because it encourages you to use a specific name when importing.

@tmeasday here’s a specific example of the confusion I was talking about.

1 Like

I guess if we use export default we need to indicate the filename somehow in the guide.

I can see the confusion here but I’m still feeling like if the file is called ListsShowPage.jsx and then exports ListShowPage it feels a little redundant.

Anyway, I can see the arguments both ways, I think for this React stuff we should just do whatever the React examples do when they switch to ES2015 modules (they still use require at this point which is closer to export default)

1 Like

We shouldn’t write ^^, instead

const ListsShowPage = createContainer(...);

export default ListsShowPage;

That would help a lot I think.

5 Likes

I like this a lot! This seems to strike a good balance between clear naming and the default export. And if someone’s an expert in ES2015 they’ll know that the intermediate variable can be omitted.