This assignment demonstrates how to use your fork of my isit-code package. We will also create an Express and React based project that calls some methods in your fork of isit-code.
Be sure lamp is installed.
To save keystrokes when typing, and cut down on noise when reading, I'll use some simple shortcuts. Unless I explicitly state otherwise, when I write isit-code, I'm referencing your isit-code-lastname project.
Use CreateExpressProject to populate a folder in your repository called Week04-UseIsitCode:
Use NPM to install your isit-code project and save a reference to it in your package.json file.
In index.js use require to load your NPM package. The call might look something like this:
const isitCode = require('isit-code-lastname');
Most of the time, however, you want to load a particule module from the library. Suppose you want the elf-utils module. Load it like this:
const elfUtils = require('isit-code-lastname').elfUtils;
Now call two methods from your isit-code package.
Create two routes in index.js, one for calling each method. The routes should have these names:
For instance:
router.get('/home-directory', function(req, res, next) { 'use strict';
I'll leave it up to you to implement the method. the call to elfUtils.homeDir is very simple. Also, you can see an example of how to call it in isit-code/spec/test-elf-utils-files.js.
NOTE: This is one of the times when a set of unit tests can be used not just for running tests, but for documenting a library. In particular, the primary documentation for isit-code is in the spec directory of the isit-code package. Though it would be good to have better document, it is often the case the unit tests included with a package can help you understand a package.
Create a file called CallIsitCode in a directory in the root of your project called source. The file should contain ES6 and React code.
THREE NOTES ON STYLE:
Create two buttons in your React component:
A click on the first button should call the appropriate method on the server. Click the second button -- and well -- you know what it should do. Use fetch from whatwg-fetch to make the calls from the client to the server.
You are going to need to create a webpack.config.js file. I would suggest you copy the one from the webpack section of the ReactBasics assignment.
You will want to put the entry to CallIsitCode. The output might look something like this:
output: {path: __dirname, filename: './public/javascripts/bundle.js'},
You should know the steps to load the ES6 code by now. But if you need a hint, consider this:
The key pieces you need at the end of index.pug are:
We put the script statement at the end of index.html because it uses the home DIV. That DIV must already be loaded or the React code won't find a place to insert itself.
Suppose you define an input control with JSX:
<input type="text" onChange={this.firstWordChange} placeholder='Enter multi-word sentence.' />
How do we get text from the input? Declare state for the input:
constructor() {
super();
this.state = {
homeDirectory: 'Unknown',
firstWord: 'Unknown',
userInput: 'Unknown' << TRACK USER INPUT
};
this.homeDirectory = this.homeDirectory.bind(this);
this.firstWordChange = this.firstWordChange.bind(this);
this.firstWord = this.firstWord.bind(this);
}
Define the firstWordChange method. It gets called over and over as the user types in the input. It also continually updates the this.state.userInput:
firstWordChange(event) {
console.log('firstWord:', event.target.value);
this.setState({userInput: event.target.value})
}
Now that we have the user input in this.state.userInput, how do we pass it to the server. Like this:
Our goal is to pass a URL to the server describing the sentence from which we want the first word:
/first-word?
First we need to define a method to URL encode the parameters:
getQuery() {
const params = {sentence: this.state.userInput};
const encodeUri = encodeURIComponent;
let query = Object.keys(params)
.map(key => encodeUri(key) + '=' + encodeUri(params[key]))
.join('&');
return query;
}
}
The join statement turns the array produced by map into a string joined on ampersands.
Then we need to use it when we call fetch:
firstWord() {
const that = this;
const query = '/first-word?' + this.getQuery();
console.log(query);
fetch(query)
.then(function(response) {
return response.json();
})
.then(function(json) {
console.log('parsed json', json);
that.setState({ firstWord: json.firstWord });
})
.catch(function(ex) {
console.log('parsing failed', ex);
});
}
And here is the code for getting the query when it is passed to the server:
router.get('/first-word', function(request, response, next) { 'use strict';
console.log(req.query);
try {
// Now call elfUtils with the sentence passed in the query.
// Use Response.send to return the result.
// Here is one way to handle an error if it occurs:
} catch(e) {
console.log(e);
res.status(500).send(e)
}
});
Place your work in a branch called Week04. When turning in the assignment, include the following information:
To get full credit, the second button must retrieve a string from the user via a TextBox. The call should retrieve the first word the user enters.
Also, consider adding the URL of your repos:
We often get errors like this:
We know that we are calling setState of this or that. So why is this undefined? There could be many reasons, by a likely culprit is that you forgot to bind a method:
this.someMethod = this.someMethod.bind(this);
Read the References section in ElvenLinks