Quickstart
A quick dive into getting started with Lore
A quick dive into getting started with Lore
In this step we're going to learn about the connect
decorator, and use it to allow our Tweet component to declare what data it needs.
You can view the finished code for this step by checking out the
fetching.3
branch of the completed project.
Lore provides a decorator (also known as a Higher Order Component) that allows components to declare what data they need, and the framework will automatically retrieve it from the API if it doesn't exist in the local store.
That decorator is called connect
and the syntax for using it looks like this:
connect(function(getState, props) {
return {
tweets: getState('tweet.find')
};
})(createReactClass({...}));
class MyComponent extends React.Component {...}
connect(function(getState, props) {
return {
tweets: getState('tweet.find')
};
})(MyComponent);
@connect(function(getState, props) {
return {
tweets: getState('tweet.find')
};
})
class MyComponent extends React.Component {...}
You can learn more about
connect
here.
The first parameter, getState
, is a function that will retrieve a piece of state from the local store, or invoke the appropriate action to retrieve that data if it hasn't been fetched yet.
The string you provide to getState()
is referred to as a "blueprint", and describes what you want the function to do. The first part, tweet
, is the resource you want to fetch, and the second part, find
, is the name of the blueprint.
In this example we're providing tweet.find
, and since we aren't passing in any query parameters or pagination information, this request translates to "make a call to the /tweets endpoint of the API and give me whatever comes back".
You can learn more about the
find
blueprint here.
The data returned will then be passed to the Feed
component through a prop named tweets
, since that's what we named the key.
To use connect
, you first need to import it from the lore-hook-connect
package, which is already included in your project (we'll introduce hooks later in this tutorial).
Open your Feed
component and wrap it with the connect
decorator like this:
// src/components/Feed.js
...
import { connect } from 'lore-hook-connect';
export default connect(function(getState, props) {
return {
tweets: getState('tweet.find')
};
})(
createReactClass({
...
})
);
// src/components/Feed.js
...
import { connect } from 'lore-hook-connect';
class Feed extends React.Component {
...
};
export default connect(function(getState, props) {
return {
tweets: getState('tweet.find')
};
})(Feed);
// src/components/Feed.js
...
import { connect } from 'lore-hook-connect';
@connect(function(getState, props) {
return {
tweets: getState('tweet.find')
};
})
class Feed extends React.Component {
...
};
export default Feed;
Once you've wrapped the Feed
component, reload the page, and you'll notice the mock data has been replaced by real data from the API.
If everything went well, your application should now look like this.
Below is a list of files modified during this step.
import React from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import { connect } from 'lore-hook-connect';
import Tweet from './Tweet';
export default connect(function(getState, props) {
return {
tweets: getState('tweet.find')
};
})(
createReactClass({
displayName: 'Feed',
propTypes: {
tweets: PropTypes.object.isRequired
},
getDefaultProps() {
const tweet = {
id: 1,
cid: 'c1',
state: 'RESOLVED',
data: {
id: 1,
userId: 1,
text: 'Nothing can beat science!',
createdAt: '2018-04-24T05:10:49.382Z'
}
};
return {
tweets: {
state: 'RESOLVED',
data: [tweet]
}
};
},
renderTweet(tweet) {
return (
<Tweet key={tweet.id} tweet={tweet} />
);
},
render() {
const { tweets } = this.props;
return (
<div className="feed">
<h2 className="title">
Feed
</h2>
<ul className="media-list tweets">
{tweets.data.map(this.renderTweet)}
</ul>
</div>
);
}
})
);
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'lore-hook-connect';
import Tweet from './Tweet';
class Feed extends React.Component {
renderTweet(tweet) {
return (
<Tweet key={tweet.id} tweet={tweet} />
);
}
render() {
const { tweets } = this.props;
return (
<div className="feed">
<h2 className="title">
Feed
</h2>
<ul className="media-list tweets">
{tweets.data.map(this.renderTweet)}
</ul>
</div>
);
}
}
Feed.propTypes = {
tweets: PropTypes.object.isRequired
};
Feed.defaultProps = (function() {
const tweet = {
id: 1,
cid: 'c1',
state: 'RESOLVED',
data: {
id: 1,
userId: 1,
text: 'Nothing can beat science!',
createdAt: '2018-04-24T05:10:49.382Z'
}
};
return {
tweets: {
state: 'RESOLVED',
data: [tweet]
}
};
})();
export default connect(function(getState, props) {
return {
tweets: getState('tweet.find')
};
})(Feed);
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'lore-hook-connect';
import Tweet from './Tweet';
@connect(function(getState, props) {
return {
tweets: getState('tweet.find')
};
})
class Feed extends React.Component {
static propTypes = {
tweets: PropTypes.object.isRequired
};
static defaultProps = (function() {
const tweet = {
id: 1,
cid: 'c1',
state: 'RESOLVED',
data: {
id: 1,
userId: 1,
text: 'Nothing can beat science!',
createdAt: '2018-04-24T05:10:49.382Z'
}
};
return {
tweets: {
state: 'RESOLVED',
data: [tweet]
}
};
})();
renderTweet(tweet) {
return (
<Tweet key={tweet.id} tweet={tweet} />
);
}
render() {
const { tweets } = this.props;
return (
<div className="feed">
<h2 className="title">
Feed
</h2>
<ul className="media-list tweets">
{tweets.data.map(this.renderTweet)}
</ul>
</div>
);
}
}
export default Feed;
Next we're going to display a loading experience while the tweets are being fetched.