Quickstart

A quick dive into getting started with Lore

Step 1: Remove Parsing

In this step we'll refactor our code so that we can remove the parse() method we added to get our application to work after setting up the real API.

While we could continue to use the parse() method, refactoring our code will make some of the later steps a little simpler.

You can view the finished code for this step by checking out the cleanup.1 branch of the completed project.

Refactor Tweet Component

To start, open the Tweet component. Locate the connect call and replace userId with user, like this:

// src/components/Tweet.js
connect(function(getState, props) {
  const { tweet } = props;

  return {
    user: getState('user.byId', {
      id: tweet.data.user
    })
  };
})
// src/components/Tweet.js
export default connect(function(getState, props) {
  const tweet = props.tweet;

  return {
    user: getState('user.byId', {
      id: tweet.data.user
    })
  };
})(Tweet);
// src/components/Tweet.js
@connect(function(getState, props) {
  const tweet = props.tweet;

  return {
    user: getState('user.byId', {
      id: tweet.data.user
    })
  };
});

With this change, we've removed the dependency we had on the userId attribute from the json-api server, and no longer have a reason for our custom parse() method.

Remove Parse from Tweet Model

Next open src/components/tweet.js and locate the parse() method that currently looks like this:

// src/models/tweet.js
export default {
  ...
  properties: {
    parse: function(response, options) {
      response.userId = response.user;
      return response;
    }
  }
  ...
}

Since we no longer need it, delete the function, or convert it back to it's commented out default, like this:

// src/models/tweet.js
export default {
  ...
  properties: {
    // parse: function(response, options) {
    //  return response;
    // }
  }
  ...
}

With these changes, your application should still work.

Visual Check-in

If everything went well, your application should look like this (exactly the same):

Code Changes

Below is a list of files modified during this step.

src/components/Tweet.js

import React from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import moment from 'moment';
import { connect } from 'lore-hook-connect';

export default connect(function(getState, props) {
  const tweet = props.tweet;

  return {
    user: getState('user.byId', {
      id: tweet.data.user
    })
  };
})(
createReactClass({
  displayName: 'Tweet',

  propTypes: {
    tweet: PropTypes.object.isRequired,
    user: PropTypes.object.isRequired
  },

  render() {
    const { tweet, user } = this.props;
    const timestamp = moment(tweet.data.createdAt).fromNow().split(' ago')[0];

    return (
      <li className="list-group-item tweet">
        <div className="image-container">
          <img
            className="img-circle avatar"
            src={user.data.avatar} />
        </div>
        <div className="content-container">
          <h4 className="list-group-item-heading title">
            {user.data.nickname}
          </h4>
          <h4 className="list-group-item-heading timestamp">
            {'- ' + timestamp}
          </h4>
          <p className="list-group-item-text text">
            {tweet.data.text}
          </p>
        </div>
      </li>
    );
  }

})
);
import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import { connect } from 'lore-hook-connect';

class Tweet extends React.Component {

  render() {
    const { tweet, user } = this.props;
    const timestamp = moment(tweet.data.createdAt).fromNow().split(' ago')[0];

    return (
      <li className="list-group-item tweet">
        <div className="image-container">
          <img
            className="img-circle avatar"
            src={user.data.avatar} />
        </div>
        <div className="content-container">
          <h4 className="list-group-item-heading title">
            {user.data.nickname}
          </h4>
          <h4 className="list-group-item-heading timestamp">
            {'- ' + timestamp}
          </h4>
          <p className="list-group-item-text text">
            {tweet.data.text}
          </p>
        </div>
      </li>
    );
  }

}

Tweet.propTypes = {
  tweet: PropTypes.object.isRequired,
  user: PropTypes.object.isRequired
};

export default connect(function(getState, props) {
  const tweet = props.tweet;

  return {
    user: getState('user.byId', {
      id: tweet.data.user
    })
  };
})(Tweet);
import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import { connect } from 'lore-hook-connect';

@connect(function(getState, props) {
  const tweet = props.tweet;

  return {
    user: getState('user.byId', {
      id: tweet.data.user
    })
  };
})
class Tweet extends React.Component {

  static propTypes = {
    tweet: PropTypes.object.isRequired,
    user: PropTypes.object.isRequired
  };

  render() {
    const { tweet, user } = this.props;
    const timestamp = moment(tweet.data.createdAt).fromNow().split(' ago')[0];

    return (
      <li className="list-group-item tweet">
        <div className="image-container">
          <img
            className="img-circle avatar"
            src={user.data.avatar} />
        </div>
        <div className="content-container">
          <h4 className="list-group-item-heading title">
            {user.data.nickname}
          </h4>
          <h4 className="list-group-item-heading timestamp">
            {'- ' + timestamp}
          </h4>
          <p className="list-group-item-text text">
            {tweet.data.text}
          </p>
        </div>
      </li>
    );
  }

}

export default Tweet;

src/models/tweet.js

export default {

};

Next Steps

Next we're going to add dialogs to our application so we can create, update and delete tweets.