Idea
Our application would not be very complicated, but I wanted to create something I need, as I think this is the best method to learn new thing – by solving some actual problem.
App would be used for rating submissions.
So we would need a form for creating new submission:
And we will display pending rated and rejected submissions in separate listings, which will be very similar. Each would have first name and last name displayed, rated ones will have additional mark and rejected ones reason.
Last view we need is submission detailed view, where you can actually perform rating:
Dependencies
Firstly we will create package.json where we will put app dependencies:
Notice also scripts attribute where we define how our application will start:
To install specified dependencies run npm install from the console.
Server
We need to create server.js then:
This creates Express application:
Which we later configure:
And we start actual server:
Index
By default Express looks for the view to render in views directory, so let’s create our index.ejs there:
There are two important things going on here.
Firstly, this is the div where all our app will be injected:
Secondly, we attach bundle.js only in development:
It’s important to do it only for development as in production we will have assets minified and with fingerprints (e.g. bundle-9bd396dbffaafe40f751.min.js). We will use Webpack plugin to inject both javascripts and stylesheets bundle for production.
Webpack
Development config
Ok, we included bundle.js but we don’t have it yet, so lets configure Webpack – create directory webpack with the file development.config.js:
We configure here entry points (see default config below), loaders (in the default config too), plugins (ExtractTextPlugin which is used to extract stylesheets to separate output file) and output (path where output will be generated, public path from where we want it to be accessible and file name (more details below).
Some parts will be shared between development and production, so I extracted them to default.config.js:
As you can see, we configure there:
- how our bundle will be named,
- on which port our server would start,
- from where our static assets will be served (we use it in server.js),
- entries which are starting point for bundling,
- loaders which we want to use:
- babel-loader for ES6,
- css-loader for ExtractTextPlugin
- sass-loader for Sass
Production config
As I mentioned, for production we want assets to be minified and attached in html with fingerprints. That’s why we have separate config:
Entry points
So we specified entry points to our application as: src/application.js, css/application.scss but we don’t have it yet, let’s create them!
Create application.scss in css directory:
And application.js in src directory:
As you can see we are rendering our application client side here, using routes we need to define in routes.js:
Let’s create only two routes for now:
This means that where we go to /submissions/new, SubmissionFormPage component will be rendered, but as a child of Main component. Which we did, Main component will be kind of template for our app, where we would have menu:
And in SubmissionFormPage we would have actual form:
Create them in src/components directory.
Connection to API
We will use Axios for connection to the backend, let’s create src/lib/Connection.js:
Displaying submissions
To check if everything is working it would be convenient to be able to see pending submissions list, so let’s create PendingSubmissionsPage:
And SubmissionsList:
Starting the app!
Now we can finally test if everything works. Run npm start in the console, and go to http://localhost:3000 in your browser.
Rating
Now we can implement rating itself.
Let’s add SubmissionPage:
And route to the src/routes.js:
Note this part:
We pass performRating handler as props to Rate component:
And further, to RateButton component:
And here we have it bind to onClick event, because only here we know particular value for rating.
That’s all!
We just created simple application, using just bare React. But as you can notice, we hold state of the app in many places so in more complicated application it can cause a lot of pain :)
In the next post we will update our app to use more structured pattern for managing the state – flux.
For now, you can now practise a bit by adding missing EvaluatedSubmissionsPage and RejectedSubmissionsPage.
See you next week!