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

Bring your web application architecture to the next level with React.JS

Bring your web application architecture to the next level with React.JS

Bastian Hofmann

June 11, 2015
Tweet

More Decks by Bastian Hofmann

Other Decks in Programming

Transcript

  1. 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
  2. So?

  3. MVC

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

    <div>Hello {this.props.name}</div>;
 }
 }
 );
 
 React.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> );
 }
 });
 
 React.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. 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() ]
 );
 }
 }
 }
  16. class PublicationItem {
 
 public $publicationId;
 public $publication;
 
 public

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

    => 'data',
 'number' => 42,
 'subComponent' => $this->subComponent,
 'someArray' => [1, 2, 3],
 'subComponentList' => [ $this->items[0], $this->items[1] ]
 ];
 }
  18. {
 "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" }
 }
 }
  19. 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>
 );
 }
 }
 );
  20. var React = require('react');
 
 module.exports = React.createClass(
 {
 displayName:

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

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

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