A quick dive into getting started with Lore

Convention over Configuration

As you'll soon see, we now have all the code required to fetch tweets from the API. Lore accomplishes this using a design paradigm called convention over configuration.

In the simplest sense, what this means is that the framework makes some assumptions about what you want, and then provides you with the ability to override those assumptions if you need to.

If you'd like to see some of this functionality demonstrated now, and are comfortable using the console provided in the developer tools for your browser, feel free to follow along with the steps below.

If not, feel free to skip this step. It is entirely optional.

Console Demo: Actions

To get started, refresh the browser and open the developer console. Then enter this command into the console:


When you created the tweet model Lore assumed you wanted a set of actions that could find, create, update and delete tweets. After creating these actions, it attached them to an object found at lore.actions.tweet.

The command you just entered invoked the find action to fetch tweets from the API, and if you examine the network tab, you'll see a GET request was sent to http://localhost:1337/tweets.

The URL for this API call was composed from a convention, which defaults to "pluralize the model name and append it to the apiRoot", but you can change this convention as needed by modifying the properties in the tweet model.

You can also fetch tweets by a specific user, by providing an object of query parameters to the find() method like this:

  userId: 1

If you examine the network tab again, you'll see a GET request was sent to http://localhost:1337/tweets?userId=1.

Console Demo: Reducers & Store State

In addition to creating a set of actions, Lore also produces a set of reducers that store the tweets returned by the API. For example, to see a list of the tweets that have been returned, enter this command into the developer console:


You should see a response that looks similar to like this:

1: {id: 1, cid: "c1", state: "RESOLVED", error: {}, data: {}}
2: {id: 2, cid: "c2", state: "RESOLVED", error: {}, data: {}}
3: {id: 3, cid: "c3", state: "RESOLVED", error: {}, data: {}}
4: {id: 4, cid: "c4", state: "RESOLVED", error: {}, data: {}}
5: {id: 5, cid: "c5", state: "RESOLVED", error: {}, data: {}}
6: {id: 6, cid: "c6", state: "RESOLVED", error: {}, data: {}}
7: {id: 7, cid: "c7", state: "RESOLVED", error: {}, data: {}}

What you're looking at in the example above is an object containing every tweet that's been returned from the API, stored using their id as the key.

And if you enter this command:


You'll be able to see an object containing the result of every query asked of the /tweets endpoint, using the query as the key:

{"where":{"userId":1},"pagination":{}}:{state: "RESOLVED", error: {}, data: Array(1), query: {}, meta: {}}
{"where":{},"pagination":{}}:{state: "RESOLVED", error: {}, data: Array(7), query: {}, meta: {}}

While this is certainly useful (we just got a lot of functionality by writing very little code), we can still do one better.

In the next section we'll learn how components can declare what data they need, and see how the framework can orchestrate calls to these actions and reducers to give us what we need automatically.

Next Steps

Next we're going to see these in actions, and connect our Feed to get real data.