Quickstart
A quick dive into getting started with Lore
A quick dive into getting started with Lore
In this step we're going create a dialog that we can use to create tweets.
You can view the finished code for this step by checking out the
dialogs.3
branch of the completed project.
Run this command to generate the component we'll use for the dialog:
lore generate component CreateTweetDialog
Then open the file and update it to look like this:
import React from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import _ from 'lodash';
export default createReactClass({
displayName: 'CreateTweetDialog',
propTypes: {
title: PropTypes.node,
description: PropTypes.node
},
getInitialState() {
return {
data: {
text: ''
}
};
},
componentDidMount() {
this.show();
},
show() {
const modal = this.refs.modal;
$(modal).modal('show');
},
dismiss() {
const modal = this.refs.modal;
$(modal).modal('hide');
},
request(data) {
console.log(data);
},
onSubmit() {
const { data } = this.state;
this.request(data);
this.dismiss();
},
onChange(name, value) {
const nextData = _.merge({}, this.state.data);
nextData[name] = value;
this.setState({
data: nextData
});
},
render() {
const { data } = this.state;
return (
<div ref="modal" className="modal fade">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" onClick={this.dismiss}>
<span>×</span>
</button>
<h4 className="modal-title">
Create Tweet
</h4>
</div>
<div className="modal-body">
<div className="row">
<div className="col-md-12">
<div className="form-group">
<label>Message</label>
<textarea
className="form-control"
rows="3"
value={data.text}
placeholder="What's happening?"
onChange={(event) => {
this.onChange('text', event.target.value)
}}
/>
</div>
</div>
</div>
</div>
<div className="modal-footer">
<div className="row">
<div className="col-md-12">
<button
type="button"
className="btn btn-default"
onClick={this.dismiss}
>
Cancel
</button>
<button
type="button"
className="btn btn-primary"
disabled={!data.text}
onClick={this.onSubmit}
>
Create
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
});
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
class CreateTweetDialog extends React.Component {
constructor(props) {
super(props);
// set initial state
this.state = {
data: {
text: ''
}
};
// bind custom methods
this.show = this.show.bind(this);
this.dismiss = this.dismiss.bind(this);
this.request = this.request.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.onChange = this.onChange.bind(this);
}
componentDidMount() {
this.show();
}
show() {
const modal = this.refs.modal;
$(modal).modal('show');
}
dismiss() {
const modal = this.refs.modal;
$(modal).modal('hide');
}
request(data) {
console.log(data);
}
onSubmit() {
const { data } = this.state;
this.request(data);
this.dismiss();
}
onChange(name, value) {
const nextData = _.merge({}, this.state.data);
nextData[name] = value;
this.setState({
data: nextData
});
}
render() {
const { data } = this.state;
return (
<div ref="modal" className="modal fade">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" onClick={this.dismiss}>
<span>×</span>
</button>
<h4 className="modal-title">
Create Tweet
</h4>
</div>
<div className="modal-body">
<div className="row">
<div className="col-md-12">
<div className="form-group">
<label>Message</label>
<textarea
className="form-control"
rows="3"
value={data.text}
placeholder="What's happening?"
onChange={(event) => {
this.onChange('text', event.target.value)
}}
/>
</div>
</div>
</div>
</div>
<div className="modal-footer">
<div className="row">
<div className="col-md-12">
<button
type="button"
className="btn btn-default"
onClick={this.dismiss}
>
Cancel
</button>
<button
type="button"
className="btn btn-primary"
disabled={!data.text}
onClick={this.onSubmit}
>
Create
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
CreateTweetDialog.propTypes = {
title: PropTypes.node,
description: PropTypes.node
};
export default CreateTweetDialog;
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
class CreateTweetDialog extends React.Component {
static propTypes = {
title: PropTypes.node,
description: PropTypes.node
};
constructor(props) {
super(props);
// set initial state
this.state = {
data: {
text: ''
}
};
// bind custom methods
this.show = this.show.bind(this);
this.dismiss = this.dismiss.bind(this);
this.request = this.request.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.onChange = this.onChange.bind(this);
}
componentDidMount() {
this.show();
}
show() {
const modal = this.refs.modal;
$(modal).modal('show');
}
dismiss() {
const modal = this.refs.modal;
$(modal).modal('hide');
}
request(data) {
console.log(data);
}
onSubmit() {
const { data } = this.state;
this.request(data);
this.dismiss();
}
onChange(name, value) {
const nextData = _.merge({}, this.state.data);
nextData[name] = value;
this.setState({
data: nextData
});
}
render() {
const { data } = this.state;
return (
<div ref="modal" className="modal fade">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" onClick={this.dismiss}>
<span>×</span>
</button>
<h4 className="modal-title">
Create Tweet
</h4>
</div>
<div className="modal-body">
<div className="row">
<div className="col-md-12">
<div className="form-group">
<label>Message</label>
<textarea
className="form-control"
rows="3"
value={data.text}
placeholder="What's happening?"
onChange={(event) => {
this.onChange('text', event.target.value)
}}
/>
</div>
</div>
</div>
</div>
<div className="modal-footer">
<div className="row">
<div className="col-md-12">
<button
type="button"
className="btn btn-default"
onClick={this.dismiss}
>
Cancel
</button>
<button
type="button"
className="btn btn-primary"
disabled={!data.text}
onClick={this.onSubmit}
>
Create
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default CreateTweetDialog;
This code will give us a Bootstrap dialog we can use to create tweets. When launched, it will fade into view, and allow us to enter the text for the tweet and submit it.
You can learn more about Bootstrap dialogs (called Modals) in the modal documentation on the Bootstrap website.
The important parts to call out here are the onSubmit()
and request()
methods shown below:
// src/components/CreateTweetDialog.js
request(data) {
console.log(data);
},
onSubmit() {
const { data } = this.state;
this.request(data);
this.dismiss();
},
// src/components/CreateTweetDialog.js
request(data) {
console.log(data);
}
onSubmit() {
const { data } = this.state;
this.request(data);
this.dismiss();
}
// src/components/CreateTweetDialog.js
request(data) {
console.log(data);
}
onSubmit() {
const { data } = this.state;
this.request(data);
this.dismiss();
}
Once the user submits the dialog, the request()
method will be invoked and make the API request to send the data to the server. But for now, we're simply going to log the data to the console, and then dismiss the dialog.
Next, open the CreateButton
component and import this dialog. Then update the onClick()
method so that it shows the dialog instead of the text "Dialog Placeholder":
// src/components/CreateButton.js
...
import CreateTweetDialog from './CreateTweetDialog';
...
onClick() {
lore.dialog.show(function() {
return (
<CreateTweetDialog />
);
});
}
...
Now when you click the button to create a dialog, a real dialog appears, and you can even fill it and submit the form, causing the data to be logged to the console.
Now we can launch a dialog and get the user input, but we aren't sending that input to the API yet. To do that we'll need to invoke the create
action, which is done like this:
lore.actions.tweet.create({
text: 'My tweet'
})
The argument you provide is an object with the attributes you want the tweet created with. In this example, we're creating a tweet and setting the text
of the tweet to "My tweet".
Invoking this action will send a POST request to http://localhost:1337/tweets
and include our attributes in the body of the request.
You can learn more about the
create
action here.
Let's finish the dialog by replacing the logging behavior with a real API call. Update the request()
method of the CreateTweetDialog
to look like this:
// src/components/CreateTweetDialog.js
request(data) {
lore.actions.tweet.create(data);
},
Now when you submit a tweet, the action will send the data to the API. Try it out!
It's important to point out that the tweets you create will not appear on the page until you refresh the browser. We'll learn how to change that behavior later in the Quickstart, so that the new tweets appear in the Feed immediately.
If everything went well, your application should now look like this when you click the "create tweet" button:
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 _ from 'lodash';
export default createReactClass({
displayName: 'CreateTweetDialog',
propTypes: {
title: PropTypes.node,
description: PropTypes.node
},
getInitialState() {
return {
data: {
text: ''
}
};
},
componentDidMount() {
this.show();
},
show() {
const modal = this.refs.modal;
$(modal).modal('show');
},
dismiss() {
const modal = this.refs.modal;
$(modal).modal('hide');
},
request(data) {
lore.actions.tweet.create(data);
},
onSubmit() {
const { data } = this.state;
this.request(data);
this.dismiss();
},
onChange(name, value) {
const nextData = _.merge({}, this.state.data);
nextData[name] = value;
this.setState({
data: nextData
});
},
render() {
const { data } = this.state;
return (
<div ref="modal" className="modal fade">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" onClick={this.dismiss}>
<span>×</span>
</button>
<h4 className="modal-title">
Create Tweet
</h4>
</div>
<div className="modal-body">
<div className="row">
<div className="col-md-12">
<div className="form-group">
<label>Message</label>
<textarea
className="form-control"
rows="3"
value={data.text}
placeholder="What's happening?"
onChange={(event) => {
this.onChange('text', event.target.value)
}}
/>
</div>
</div>
</div>
</div>
<div className="modal-footer">
<div className="row">
<div className="col-md-12">
<button
type="button"
className="btn btn-default"
onClick={this.dismiss}
>
Cancel
</button>
<button
type="button"
className="btn btn-primary"
disabled={!data.text}
onClick={this.onSubmit}
>
Create
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
});
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
class CreateTweetDialog extends React.Component {
constructor(props) {
super(props);
// set initial state
this.state = {
data: {
text: ''
}
};
// bind custom methods
this.show = this.show.bind(this);
this.dismiss = this.dismiss.bind(this);
this.request = this.request.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.onChange = this.onChange.bind(this);
}
componentDidMount() {
this.show();
}
show() {
const modal = this.refs.modal;
$(modal).modal('show');
}
dismiss() {
const modal = this.refs.modal;
$(modal).modal('hide');
}
request(data) {
lore.actions.tweet.create(data);
}
onSubmit() {
const { data } = this.state;
this.request(data);
this.dismiss();
}
onChange(name, value) {
const nextData = _.merge({}, this.state.data);
nextData[name] = value;
this.setState({
data: nextData
});
}
render() {
const { data } = this.state;
return (
<div ref="modal" className="modal fade">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" onClick={this.dismiss}>
<span>×</span>
</button>
<h4 className="modal-title">
Create Tweet
</h4>
</div>
<div className="modal-body">
<div className="row">
<div className="col-md-12">
<div className="form-group">
<label>Message</label>
<textarea
className="form-control"
rows="3"
value={data.text}
placeholder="What's happening?"
onChange={(event) => {
this.onChange('text', event.target.value)
}}
/>
</div>
</div>
</div>
</div>
<div className="modal-footer">
<div className="row">
<div className="col-md-12">
<button
type="button"
className="btn btn-default"
onClick={this.dismiss}
>
Cancel
</button>
<button
type="button"
className="btn btn-primary"
disabled={!data.text}
onClick={this.onSubmit}
>
Create
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
CreateTweetDialog.propTypes = {
title: PropTypes.node,
description: PropTypes.node
};
export default CreateTweetDialog;
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
class CreateTweetDialog extends React.Component {
static propTypes = {
title: PropTypes.node,
description: PropTypes.node
};
constructor(props) {
super(props);
// set initial state
this.state = {
data: {
text: ''
}
};
// bind custom methods
this.show = this.show.bind(this);
this.dismiss = this.dismiss.bind(this);
this.request = this.request.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.onChange = this.onChange.bind(this);
}
componentDidMount() {
this.show();
}
show() {
const modal = this.refs.modal;
$(modal).modal('show');
}
dismiss() {
const modal = this.refs.modal;
$(modal).modal('hide');
}
request(data) {
lore.actions.tweet.create(data);
}
onSubmit() {
const { data } = this.state;
this.request(data);
this.dismiss();
}
onChange(name, value) {
const nextData = _.merge({}, this.state.data);
nextData[name] = value;
this.setState({
data: nextData
});
}
render() {
const { data } = this.state;
return (
<div ref="modal" className="modal fade">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" onClick={this.dismiss}>
<span>×</span>
</button>
<h4 className="modal-title">
Create Tweet
</h4>
</div>
<div className="modal-body">
<div className="row">
<div className="col-md-12">
<div className="form-group">
<label>Message</label>
<textarea
className="form-control"
rows="3"
value={data.text}
placeholder="What's happening?"
onChange={(event) => {
this.onChange('text', event.target.value)
}}
/>
</div>
</div>
</div>
</div>
<div className="modal-footer">
<div className="row">
<div className="col-md-12">
<button
type="button"
className="btn btn-default"
onClick={this.dismiss}
>
Cancel
</button>
<button
type="button"
className="btn btn-primary"
disabled={!data.text}
onClick={this.onSubmit}
>
Create
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default CreateTweetDialog;
import React from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import CreateTweetDialog from './CreateTweetDialog';
export default createReactClass({
displayName: 'CreateButton',
onClick() {
lore.dialog.show(function() {
return (
<CreateTweetDialog />
);
});
},
render() {
return (
<button
type="button"
className="btn btn-primary btn-lg create-button"
onClick={this.onClick}>
+
</button>
);
}
});
import React from 'react';
import PropTypes from 'prop-types';
import CreateTweetDialog from './CreateTweetDialog';
class CreateButton extends React.Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
}
onClick() {
lore.dialog.show(function() {
return (
<CreateTweetDialog />
);
});
}
render () {
return (
<button
type="button"
className="btn btn-primary btn-lg create-button"
onClick={this.onClick}>
+
</button>
);
}
}
export default CreateButton;
import React from 'react';
import PropTypes from 'prop-types';
import CreateTweetDialog from './CreateTweetDialog';
class CreateButton extends React.Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
}
onClick() {
lore.dialog.show(function() {
return (
<CreateTweetDialog />
);
});
}
render () {
return (
<button
type="button"
className="btn btn-primary btn-lg create-button"
onClick={this.onClick}>
+
</button>
);
}
}
export default CreateButton;
Next we're going finish adding the create dialog.