Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Bring Your Web Application Architecture to the ...

Bring Your Web Application Architecture to the Next Level With React.JS

React.JS is a very powerful library for building user interfaces and the new, cool kid in the JavaScript world. But it is also very interesting for creating a fast, maintainable and interactive web application. In this talk I'll show what React is all about and how you can combine and integrate it’s power with your web application, even if you have to render out HTML on the server side. Especially common pitfalls for getting data from your backend to React will be covered. The result will be a flexible, component based architecture that enables developers to take page elements, like a single "follow" button, and place it everywhere on the site without having to duplicate any backend code, JS, HTML, CSS or AJAX endpoints in the process.

Bastian Hofmann

April 10, 2016
Tweet

More Decks by Bastian Hofmann

Other Decks in Programming

Transcript

  1. ?

  2. de duplication ode duplication code duplication code duplication code duplication

    code duplication code duplication code duplication code duplication code duplication code duplication code duplication code duplication code duplicatio code duplicat code duplic code dup code du code cod co co
  3. MVC

  4. var HelloMessage = React.createClass(
 {
 render: function () {
 return

    <div>Hello {this.props.name}</div>;
 }
 }
 );
 
 ReactDOM.render(<HelloMessage name="John" />, mountNode);
  5. var Timer = React.createClass({
 getInitialState: function () {
 return {secs:

    0};
 },
 tick: function () {
 this.setState({secs: this.state.secs + 1});
 },
 componentDidMount: function () {
 this.interval = setInterval(this.tick, 1000);
 },
 componentWillUnmount: function () {
 clearInterval(this.interval);
 },
 render: function () {
 return (<div> Seconds Elapsed: {this.state.secs}</div> );
 }
 });
 
 ReactDOM.render(<Timer />, mountNode);
  6. var TodoList = React.createClass(
 {
 render: function () {
 var

    createItem = function (itemText) {
 return <li>{itemText}</li>;
 };
 return ( <ul> {this.props.items.map(createItem)} </ul> );
 }
 }
 );
  7. var TodoApp = React.createClass({
 render: function () {
 return (


    <div>
 <h3>TODO</h3>
 <TodoList items={this.props.items} />
 </div>
 );
 }
 });
  8. var TodoApp = React.createClass({
 getInitialState: function () {
 return {items:

    […]};
 },
 render: function () {
 return (
 <div>
 <h3>TODO</h3>
 <TodoList items={this.state.items} />
 </div>
 );
 }
 });
  9. Profile Publications Publication Publication Publication AboutMe LeftColumn Image Menu Account

    Account Account Account Account Publication1 Publication2 Publication3 Institution
  10. Widget Widget Widget Widget Preparer Resolver Resolver Services Connector Interfaces

    Connector Implementations Batch requirements and pass them to resolvers
  11. Widget Widget Widget Widget Preparer Resolver Resolver Services Connector Interfaces

    Connector Implementations Call Services as effective as possible (Multi-GET,...)
  12. Widget Widget Widget Widget Preparer Resolver Resolver Services Connector Interfaces

    Connector Implementations Attach fetched data to Requirements and pass them back to the preparer
  13. Widget Widget Widget Widget Preparer Resolver Resolver Services Connector Interfaces

    Connector Implementations Distribute fetched data to the widgets that required it
  14. public function collect() {
 yield [
 new EntityRequirement(
 'account',
 Account::class,


    ['id' => $this->request->get('id')]
 ),
 ];
 
 yield [
 new ServiceRequirement(
 'scienceDisciplines',
 AccountService::class,
 'getScienceDisciplines',
 ['account' => $this->account]
 )
 ];
 }
  15. var TodoApp = React.createClass({
 getInitialState: function () {
 return {items:

    […]};
 },
 render: function () {
 return (
 <div>
 <h3>TODO</h3>
 <TodoList items={this.state.items} />
 </div>
 );
 }
 });
  16. class PublicationKeywordSearch {
 
 public $publications;
 public $publicationListItems = [];


    
 public function collect() {
 yield [
 serviceRequirement(
 'publications',
 PublicationService::getCall()->getByKeywords(
 ['virology', 'cancer'], 10, 0
 )
 )
 ];
 foreach ($this->publications as $publication) {
 yield new WidgetRequirement(
 'publicationListItems',
 PublicationItem::CLASS,
 [ 'publicationId' => $publication->getId() ]
 );
 }
 }
 }
  17. class PublicationItem {
 
 public $publicationId;
 public $publication;
 
 public

    function collect() {
 yield new RequestDataRequirement('publicationId');
 yield [
 new EntityRequirement(
 'publication',
 Publication::class,
 ['id' => $this->publicationId]
 )
 ];
 }
 }
  18. public function getData() {
 return [
 'key' => 'value',
 'other'

    => 'data',
 'number' => 42,
 'subComponent' => $this->subComponent,
 'someArray' => [1, 2, 3],
 'subComponentList' => [ $this->items[0], $this->items[1] ]
 ];
 }
  19. {
 "ParentComponent-1234": {
 "component": "ParentComponent.jsx",
 "id": "ParentComponent-1234",
 "data": {
 "key":

    "value",
 "other": "data",
 "number": 42,
 "subComponent": "SubComponent",
 "someArray": [1, 2, 3],
 "subComponentList": [ "ListItem-444", "ListItem-555"]
 }
 },
 "SubComponent": {
 "component": "SubComponent.jsx",
 "id": "SubComponent",
 "data": { "boolValue": true }
 },
 "ListItem-444": {
 "component": "ListItem",
 "id": "ListItem-444",
 "data": { "title": "444s title“ }
 },
 "ListItem-555": {
 "component": "ListItem",
 "id": "ListItem-555",
 "data": { "title": "555s title" }
 }
 }
  20. var React = require('react');
 var SubComponent = require('SubComponent');
 var ListItem

    = require('ListItem');
 
 module.exports = React.createClass(
 {
 displayName: 'ParentComponent',
 render: function () {
 var items = [];
 
 for (var key in this.props.subComponentList) {
 if (this.props.subComponentList.hasOwnProperty(key)) {
 items.push(
 <li>
 <ListItem componentId={this.props.subComponentList[key]}/>
 </li>
 );
 }
 }
 
 return (
 <div className="{this.props.key}">
 <h1>{this.props.other} Hello PHP {this.props.number}</h1>
 <SubComponent componentId={this.props.subComponent} />
 <ul>{items}</ul>
 </div>
 );
 }
 }
 );
  21. var React = require('react');
 
 module.exports = React.createClass(
 {
 displayName:

    'ListItem',
 render: function () {
 return (
 <div>
 {this.props.title}
 </div>
 );
 }
 }
 );
  22. SEO

  23. Profile Publications Publication Publication Publication AboutMe LeftColumn Image Menu <div

    id="placeholder"></div> <script>loadWidget('/aboutMe', function(w) { w.render({ replace : '#placeholder' }); })</script> Institution