Features
Key features that make up the main value proposition for Lore
Key features that make up the main value proposition for Lore
Useful for viewing a subset of data that matches a specific criteria.
This video demonstrates what filtering looks like. Screenshots are from the Simply Social prototype that Invision provides you when you sign up for an account.
Let's say you have an API with a /posts
endpoint, and you want to retrieve a list of Posts created by the Author whose id is 123
. To do that, pass a where
clause to the connect
call like this:
@connect(function(getState, props) {
return {
posts: getState('post.find', {
where: {
authorId: '123'
}
})
};
})
Assuming your API server is located at http://api.example.com
, this call will get transformed into the following network request:
http://api.example.com/posts?authorId=123
Lore's default behavior is to convert the where
clause into a query string. So if you passed in a second property to the where
clause, like this:
where: {
authorId: '123',
title: 'Bacon'
}
It would get converted into this network request:
http://api.example.com/posts?authorId=123&title=Bacon
Since it will take time for the network request to complete, let's focus on the component next. The component is going to receive a prop named posts
containing the result of our request for data.
@connect(function(getState, props) {
return {
posts: getState('post.find', {
where: {
authorId: '123'
}
})
};
})
class Component extends React.Component {
static propTypes = {
posts: React.PropTypes.object.isRequired
};
render() {
var posts = this.props.posts;
// todo: render the posts
}
};
Since our network request was just sent out, we won't have any data yet. So posts
will look like this:
posts = {
state: 'FETCHING',
data: [],
query: { where: { authorId: '123' } }
}
We don't have any data to render yet, but the query
field is a stringified JSON that tells us what data we asked for, and the state
field tells us that data is being fetched. So let's render a loading message while we're waiting for the data to return from the API server.
@connect(function(getState, props) {
return {
posts: getState('post.find', {
where: {
authorId: props.params.authorId
}
})
};
})
class Component extends React.Component {
static propTypes = {
posts: React.PropTypes.object.isRequired
};
render() {
var posts = this.props.posts;
if (posts.state === PayloadStates.FETCHING) {
return (
<div>Loading posts...</div>
);
}
// todo: render posts
}
};
After a time our network request will come back, the Redux store will be updated, and our component will be rerendered. But this time we'll actually have data, so our posts
will look like this:
posts = {
state: 'RESOLVED',
data: [
{
id: '1',
cid: 'c1',
state: 'RESOLVED',
data: {
title: 'Bacon is yummy',
authorId: '123'
}
},
{
id: '2',
cid: 'c1',
state: 'RESOLVED',
data: {
title: 'An ode to Bacon',
authorId: '123'
}
}
],
query: { where: { authorId: '123' } }
}
The state
value of RESOLVED
let's you know that nothing is happening; the request has been resolved. And now, ourdata
property contains an array of Posts
. So let's render that array to display the lists of posts by that author:
connect(function(getState, props) {
return {
posts: getState('post.find', {
where: {
authorId: props.params.authorId
}
})
};
})(
createReactClass({
propTypes: {
posts: React.PropTypes.object.isRequired
},
render: function() {
var posts = this.props.posts;
if (posts.state === PayloadStates.FETCHING) {
return (
<div>Loading posts...</div>
);
}
return (
<ul>
{posts.data.map((post) => {
return (
<li key={post.id || post.cid}>
{post.data.title}
</li>
);
})}
</ul>
);
}
})
);
Example code showing how to filter data.
connect(function(getState, props) {
return {
posts: getState('post.find', {
where: {
authorId: props.params.authorId
}
})
};
})(
createReactClass({
propTypes: {
posts: React.PropTypes.object.isRequired
},
renderPost: function(post) {
return (
<li key={post.id || post.cid}>
{post.data.title}
</li>
);
},
render: function() {
var posts = this.props.posts;
if (posts.state === PayloadStates.FETCHING) {
return (
<div>Loading posts...</div>
);
}
return (
<ul>
{posts.data.map(this.renderPost)}
</ul>
);
}
})
);
class Component extends React.Component {
constructor(props) {
super(props);
this.renderPost = this.renderPost.bind(this);
}
renderPost(post) {
return (
<li key={post.id || post.cid}>
{post.data.title}
</li>
);
}
render() {
var posts = this.props.posts;
if (posts.state === PayloadStates.FETCHING) {
return (
<div>Loading posts...</div>
);
}
return (
<ul>
{posts.data.map(this.renderPost)}
</ul>
);
}
};
Component.PropTypes = {
posts: React.PropTypes.object.isRequired
};
export default connect(function(getState, props) {
return {
posts: getState('post.find', {
where: {
authorId: props.params.authorId
}
})
};
})(Component);
@connect(function(getState, props) {
return {
posts: getState('post.find', {
where: {
authorId: props.params.authorId
}
})
};
})
class Component extends React.Component {
static propTypes = {
posts: React.PropTypes.object.isRequired
};
constructor(props) {
super(props);
this.renderPost = this.renderPost.bind(this);
}
renderPost(post) {
return (
<li key={post.id || post.cid}>
{post.data.title}
</li>
);
}
render() {
var posts = this.props.posts;
if (posts.state === PayloadStates.FETCHING) {
return (
<div>Loading posts...</div>
);
}
return (
<ul>
{posts.data.map(this.renderPost)}
</ul>
);
}
};