Contenu connexe Similaire à EWD 3 Training Course Part 37: Building a React.js application with ewd-xpress Part 1 (20) EWD 3 Training Course Part 37: Building a React.js application with ewd-xpress Part 11. Copyright © 2016 M/Gateway Developments Ltd
EWD 3 Training Course
Part 37
Building a React.js-based
QEWD Application
(a) Getting started
Rob Tweed
Director, M/Gateway Developments Ltd
Twitter: @rtweed
2. Copyright © 2016 M/Gateway Developments Ltd
Assumptions
• You understand the basic principles of
React.js
• If not, try taking this introductory course:
– https://www.udemy.com/introduction-to-reactjs
• You've installed Node.js and an
appropriate database:
– Windows or OS X: Caché or GlobalsDB
– Linux: Redis, Caché, GlobalsDB or GT.M
3. Copyright © 2016 M/Gateway Developments Ltd
Setting up the React.js Environment
• Ensure that you've installed:
– QEWD
– qewd-monitor
– ewd-client
• If you haven't done so, here's how:
– cd ~/qewd // or wherever you want your QEWD environment
– npm install qewd qewd-monitor ewd-client
4. Copyright © 2016 M/Gateway Developments Ltd
If you're using Linux
• You can use the QEWD / React installer:
cd ~
wget https://raw.githubusercontent.com/robtweed/qewd/master/installers/reactEnvironment.sh
source reactEnvironment.sh
5. Copyright © 2016 M/Gateway Developments Ltd
Otherwise do it manually
cd ~/qewd
npm install react react-dom babelify babel-preset-react react-bootstrap
npm install react-toastr react-select socket.io-client
npm install jquery ewd-client ewd-react-tools qewd-react
npm install -g browserify
npm install -g uglify-js
6. Copyright © 2016 M/Gateway Developments Ltd
Create a new application folder
cd qewdwww
mkdir react-demo1
cd react-demo1
npm install babel-preset-es2015
8. Copyright © 2016 M/Gateway Developments Ltd
index.html
~/qewd/www/react-demo1/index.html
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title id="QEWD React.js Example"></title>
</head>
<body>
<div id="content"></div>
<script src="bundle.js"></script>
</body>
</html>
9. Copyright © 2016 M/Gateway Developments Ltd
app.js
~/qewd/www/react-demo1/app.js
var reactLoader = require('qewd-react').loader;
var params = {
applicationName: 'react-demo1',
MainPage: require('./MainPage')
};
reactLoader(params);
10. Copyright © 2016 M/Gateway Developments Ltd
MainPage.js
c:ewd3wwwreact-demo1MainPage.js
"use strict"
var React = require('react');
var MainPage = React.createClass({
render: function() {
console.log('rendering MainPage');
return (
<div>
This is my test React.js Application
</div>
);
}
});
module.exports = MainPage;
11. Copyright © 2016 M/Gateway Developments Ltd
Bundle it
cd ~/qewd/www/react-demo1
browserify -t [ babelify --compact false --presets [es2015 react] ] app.js > bundle.js
You should now see bundle.js in the ~/qewd/www/react-demo1 folder
14. Copyright © 2016 M/Gateway Developments Ltd
It's a standard React.js App…
• But it has automated:
– EWD 3 / ewd-client startup
– QEWD application registration
• Used qewd-react.loader to do this
15. Copyright © 2016 M/Gateway Developments Ltd
The startup sequence
• Explained in an earlier part of the course:
– Wait until the browser's DOM is ready
– Then invoke EWD.start()
• Passing socket.io object as an argument if using
web-sockets
– When EWD has started
• You need to wait until your QEWD application has
been registered in the QEWD back-end
– Now your application is ready for user interaction
16. Copyright © 2016 M/Gateway Developments Ltd
Doing this in React is more tricky
• Must use React's life-cycle methods
– If any of these are invoked, DOM is ready
• Can therefore start EWD within them
– BUT the top-level component will still render while EWD is
starting
– SO you need two render alternatives, dependent on a state
variable's value
• 'Please wait' message; or
• Render the application's main component
– AND
• reset the state variable's value when EWD has started and
application has been registered
• pass EWD object into main component as a prop
17. Copyright © 2016 M/Gateway Developments Ltd
A lot to remember
• Need to do all of these things every time you
want to start any QEWD application
– Lots to remember and potentially go wrong
– Ideal candidate for automation
• So all this behaviour is pre-written for you in the
qewd-react module
– Let it do all that startup stuff
– You just focus on the main and subsequent modules
for your application
18. Copyright © 2016 M/Gateway Developments Ltd
By all means take a look
• ~/qewd/node_modules/qewd-react
– /lib/loader.js
– Uses the componentWillMount() and
componentDidMount() lifecycle methods
• EWD is started in the latter
– Uses a state variable that flips when your application
is registered
• Causing your main component to render
• It's then over to you
19. Copyright © 2016 M/Gateway Developments Ltd
Hierarchy of Components
• Your QEWD application must be written as a
hierarchy of React components
– Each is a self-contained module
– Each one will need access to the EWD object
• To send messages to the QEWD back-end
• To handle responses/messages sent/returned from the
QEWD back-end
• Components are bundled for use in browser
– Using WebPack or Browserify
20. Copyright © 2016 M/Gateway Developments Ltd
We saw this before
• See Part 30 of this course (Modularising QEWD
Applications)
– From around slide 55
• The EWD object must be made available to
each module
– BUT it must be the post-registration instance of the
EWD object
• So it has the send() method, etc and session token available
21. Copyright © 2016 M/Gateway Developments Ltd
How's this done with React?
Let's look at the render() function in that loader module…
22. Copyright © 2016 M/Gateway Developments Ltd
How's this done with React?
render: function render() {
var componentPath = ['app'];
var renderComponent;
if (this.state.status === 'wait') {
renderComponent = React.createElement(
'div',
null,
'Please wait...'
);
} else {
renderComponent = React.createElement(MainPage, {
controller: this.controller,
componentPath: componentPath
});
}
return renderComponent;
}
});
23. Copyright © 2016 M/Gateway Developments Ltd
How's this done with React?
render: function render() {
var componentPath = ['app'];
var renderComponent;
if (this.state.status === 'wait') {
renderComponent = React.createElement(
'div',
null,
'Please wait...'
);
} else {
renderComponent = React.createElement(MainPage, {
controller: this.controller,
componentPath: componentPath
});
}
return renderComponent;
}
});
Here's the "Please wait"
message which appears
while EWD is starting and
application is being registered
24. Copyright © 2016 M/Gateway Developments Ltd
How's this done with React?
render: function render() {
var componentPath = ['app'];
var renderComponent;
if (this.state.status === 'wait') {
renderComponent = React.createElement(
'div',
null,
'Please wait...'
);
} else {
renderComponent = React.createElement(MainPage, {
controller: this.controller,
componentPath: componentPath
});
}
return renderComponent;
}
});
Here's how it invokes
your main component
instead, once everything
has started
25. Copyright © 2016 M/Gateway Developments Ltd
How's this done with React?
render: function render() {
var componentPath = ['app'];
var renderComponent;
if (this.state.status === 'wait') {
renderComponent = React.createElement(
'div',
null,
'Please wait...'
);
} else {
renderComponent = React.createElement(MainPage, {
controller: this.controller,
componentPath: componentPath
});
}
return renderComponent;
}
});
Here's how it invokes
your main component
instead, once everything
has started
Your main component
is referred to as
MainPage
26. Copyright © 2016 M/Gateway Developments Ltd
Where's the EWD object?
render: function render() {
var componentPath = ['app'];
var renderComponent;
if (this.state.status === 'wait') {
renderComponent = React.createElement(
'div',
null,
'Please wait...'
);
} else {
renderComponent = React.createElement(MainPage, {
controller: this.controller,
componentPath: componentPath
});
}
return renderComponent;
}
});
But where is the EWD
object?
27. Copyright © 2016 M/Gateway Developments Ltd
Where's the EWD object?
render: function render() {
var componentPath = ['app'];
var renderComponent;
if (this.state.status === 'wait') {
renderComponent = React.createElement(
'div',
null,
'Please wait...'
);
} else {
renderComponent = React.createElement(MainPage, {
controller: this.controller,
componentPath: componentPath
});
}
return renderComponent;
}
});
This is it
28. Copyright © 2016 M/Gateway Developments Ltd
Where's the EWD object?
render: function render() {
var componentPath = ['app'];
var renderComponent;
if (this.state.status === 'wait') {
renderComponent = React.createElement(
'div',
null,
'Please wait...'
);
} else {
renderComponent = React.createElement(MainPage, {
controller: this.controller,
componentPath: componentPath
});
}
return renderComponent;
}
});
EWD is part of
an object I've called
the controller
29. Copyright © 2016 M/Gateway Developments Ltd
Where's the EWD object?
render: function render() {
var componentPath = ['app'];
var renderComponent;
if (this.state.status === 'wait') {
renderComponent = React.createElement(
'div',
null,
'Please wait...'
);
} else {
renderComponent = React.createElement(MainPage, {
controller: this.controller,
componentPath: componentPath
});
}
return renderComponent;
}
});
EWD is part of
an object I've called
the controller
This object is
instantiated for you
and passed to your
Main module as a
prop named controller
30. Copyright © 2016 M/Gateway Developments Ltd
Separation of Concerns
• An important principle of modern web
application development is separation of
concerns
– Move away from monolithic programming
– Each key aspect of an application is kept
separate
• Easier to maintain and understand
• More scalable as application grows in size
31. Copyright © 2016 M/Gateway Developments Ltd
React focuses on the View
• Your React components should just
describe the View aspect of your
application
– What it looks like under various situations as
the application is used
• The other aspects of your application,
commonly referred to as the Model and
Controller, should, for best practice, be
kept separate from the View
32. Copyright © 2016 M/Gateway Developments Ltd
The controller object
• Provides a place to describe the dynamic
behaviour that needs to take place in any
of your application's React components
• The controller object is passed as a prop
to any of your components that requires
dynamic behaviour
33. Copyright © 2016 M/Gateway Developments Ltd
The controller object
• The controller object is initially created for
you by the qewd-react loader module and
passed to your MainPage module as a
prop
– You refer to it as this.props.controller
– The controller object includes within it the
post-registration EWD object
• eg this.props.controller.send() allows you to send
messages to the QEWD back-end
34. Copyright © 2016 M/Gateway Developments Ltd
The controller object
• The idea is for you to extend the controller object
in each of your React components to define the
behaviour of that component:
– Events
– Messages to be sent
– Responses to be handled
– Corresponding changes to state variables within the
component
• Which cause a re-render of the component and its child
components
35. Copyright © 2016 M/Gateway Developments Ltd
Passing on the controller object
• qewd-react's loader module creates the
controller object for you and passes it to
your MainPage component
• It's up to you to pass it on to any of your
other React components as a prop
37. Copyright © 2016 M/Gateway Developments Ltd
index.html
~/qewd/www/react-demo1/index.html
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title id="QEWD React.js Example"></title>
</head>
<body>
<div id="content"></div>
<script src="bundle.js"></script>
</body>
</html>
Place-holder div into which
React renders its generated
mark-up
Your application will be built
up from within this div
Always give it an id of 'content'
38. Copyright © 2016 M/Gateway Developments Ltd
index.html
~/qewd/www/react-demo1/index.html
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title id="ewd-xpress React.js Example"></title>
</head>
<body>
<div id="content"></div>
<script src="bundle.js"></script>
</body>
</html>
Load the bundled
application's Javascript
into the browser
You'll use Browserify
or WebPack to turn your
hierarchy of React
Components into a
bundle file
39. Copyright © 2016 M/Gateway Developments Ltd
app.js
~/qewd/www/react-demo1/app.js
var reactLoader = require('qewd-react').loader;
var params = {
applicationName: 'react-demo1',
MainPage: require('./MainPage')
};
reactLoader(params);
This is the top level of
your React application's
hierarchy of modules
40. Copyright © 2016 M/Gateway Developments Ltd
app.js
~/qewd/www/react-demo1/app.js
var reactLoader = require('qewd-react').loader;
var params = {
applicationName: 'react-demo1',
MainPage: require('./MainPage')
};
reactLoader(params);
This is the top level of
your React application's
hierarchy of modules
It makes use of the
qewd-react
loader to get everything
started
41. Copyright © 2016 M/Gateway Developments Ltd
app.js
~/qewd/www/react-demo1/app.js
var reactLoader = require('qewd-react').loader;
var params = {
applicationName: 'react-demo1',
MainPage: require('./MainPage')
};
reactLoader(params);
You just define two things:
42. Copyright © 2016 M/Gateway Developments Ltd
app.js
~/qewd/www/react-demo1/app.js
var reactLoader = require('qewd-react').loader;
var params = {
applicationName: 'react-demo1',
MainPage: require('./MainPage')
};
reactLoader(params);
You just define two things:
The application name
This is the name that will
be used by ewd-xpress
to register it
43. Copyright © 2016 M/Gateway Developments Ltd
app.js
~/qewd/www/react-demo1/app.js
var reactLoader = require('qewd-react').loader;
var params = {
applicationName: 'react-demo1',
MainPage: require('./MainPage')
};
reactLoader(params);
You just define two things:
Your Application's effective
top-level Component
Referred to as MainPage
but your component file
can be named what you like
Note: you use
require() to load the file
44. Copyright © 2016 M/Gateway Developments Ltd
MainPage.js
~/qewd/www/react-demo1/MainPage.js
"use strict"
var React = require('react');
var MainPage = React.createClass({
render: function() {
console.log('rendering MainPage');
return (
<div>
This is my test React.js Application
</div>
);
}
});
module.exports = MainPage;
So as far as you're concerned,
this is your top component
By the time it is invoked,
EWD has started and
the application is
registered by QEWD
45. Copyright © 2016 M/Gateway Developments Ltd
MainPage.js
~/qewd/www/react-demo1/MainPage.js
"use strict"
var React = require('react');
var MainPage = React.createClass({
render: function() {
console.log('rendering MainPage');
return (
<div>
This is my test React.js Application
</div>
);
}
});
module.exports = MainPage;
Here we're not doing
anything except displaying
this text
46. Copyright © 2016 M/Gateway Developments Ltd
Then we bundled it
cd ~/qewd/www/react-demo1
browserify -t [ babelify --compact false --presets [es2015 react] ] app.js > bundle.js
We told Browserify to start with app.js
It automatically threads its way down through any require() functions
47. Copyright © 2016 M/Gateway Developments Ltd
Then we bundled it
cd ~/qewd/www/react-demo1
browserify -t [ babelify --compact false --presets [es2015 react] ] app.js > bundle.js
We told Browserify to start with app.js
It automatically threads its way down through any require() functions
and combines all the JavaScript into a single file named bundle.js
48. Copyright © 2016 M/Gateway Developments Ltd
So when we start the app
~/qewd/www/react-demo1/index.html
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title id="QEWD React.js Example"></title>
</head>
<body>
<div id="content"></div>
<script src="bundle.js"></script>
</body>
</html>
The index.html
file is loaded into
the browser, and it
then loads the
bundled JavaScript
file
50. Copyright © 2016 M/Gateway Developments Ltd
And what we see is…
The application is registered
51. Copyright © 2016 M/Gateway Developments Ltd
And what we see is…
And displays the text defined
in your MainPage component
52. Copyright © 2016 M/Gateway Developments Ltd
It's not doing much so far
~/qewd/www/react-demo1/MainPage.js
"use strict"
var React = require('react');
var MainPage = React.createClass({
render: function() {
console.log('rendering MainPage');
return (
<div>
This is my test React.js Application
</div>
);
}
});
module.exports = MainPage;
We'll start to build it out
in the next part of the course
53. Copyright © 2016 M/Gateway Developments Ltd
It's not doing much so far
~/qewd/www/react-demo1/MainPage.js
"use strict"
var React = require('react');
var MainPage = React.createClass({
render: function() {
console.log('rendering MainPage');
return (
<div>
This is my test React.js Application
</div>
);
}
});
module.exports = MainPage;
We'll make it send a message
To QEWD and return
a response that we display
See the next part of this course