Upload
sencha
View
171
Download
1
Embed Size (px)
Citation preview
Ext JS + ReactA Match Made in UX Heaven
Mark BrocatoSr. Engineering Manager, Sencha
My Journey to React
My Journey to React
Scenario Builder
My Journey to React
My Journey to React
My Journey to React
My Journey to React
React Primer
• A JavaScript library for building user interfaces
• React is the just the V in MVC
• Solve one problem: Build large applications with data that changes over time.
React Components
Componentdata
HTML
Views as Pure Functions
dataHTMLFunction
Views as Componentsimport React, { Component } from 'react'; class NewsFeed extends Component { render() { const { news } = this.props; return ( <ul> { news.map(story => ( <li> <div className="title">{story.title}</div> <div>by {story.author}</div> </li> )) } </ul> ) } }
Views as Pure Functions
function NewsFeed({ news }) { return ( <ul> { news.map(story => ( <li> <div className="title">{story.title}</div> <div>by {story.author}</div> </li> )) } </ul> ) }
JSX
<div className="title">{story.title}</div>
JSX
<div className="title">{story.title}</div>
React.createElement('div', { className: 'title'}, store.title)
Views as Components
function NewsFeed({ news }) { return ( React.createElement('ul', {}, news.map(story => { return React.createElement('li', {}, [ React.createElement('div', { className: 'title' }, store.title), React.createElement('div', { }, `by ${store.author}`) ]) })); ) }
React’s One-Way Data Flow (Flux)
Store
Component Component Component
Component Component Component Component
dataAPI
Virtual DOM to the Rescue
React and Ext JS Similarities
• Ext.Component
• configs
• items: []
• React.Component
• props
• children
What’s Missing?
✔ Routing: react-router✔ Architecture: redux
Components
@extjs/reactor
React Hello Worldimport React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( ( <div> Hello World! </div> ), document.getElementById('root') );
React Hello World w/ Ext JSimport React from 'react'; import ReactDOM from 'react-dom'; import install from ’@extjs/reactor'; install(); Ext.onReady(() => { ReactDOM.render( ( <x-panel title="Ext JS in React"> Hello World! </x-panel> ), document.getElementById('root') ); });
@extjs/reactor
• Use any xtype as a JSX tag.
• Mix and match HTML and Ext JS
import React from 'react'; import ReactDOM from 'react-dom'; import install from ’@extjs/reactorjs'; install(); Ext.onReady(() => { ReactDOM.render( ( <x-panel title="Ext JS in React"> Hello World! </x-panel> ), document.getElementById('root') ); });
Ext.create({ xtype: 'panel', title: 'Ext JS in React', html: 'Hello World!'});
Responding to Events
• All props starting with “on” are automatically converted to Ext JS event listeners
• You can also specify event handlers using a listeners prop, just like in traditional Ext JS
import React, { Component } from 'react'; class MyComponent extends Component { onSliderChange(slider, value) { console.log('value', value); } render() { return ( <x-slider
onChange={this.onSliderChange.bind(this)}/>
) } }
Responding to Events
• All props starting with “on” are automatically converted to Ext JS event listeners
• You can also specify event handlers using a listeners prop, just like in traditional Ext JS
import React, { Component } from 'react'; class MyComponent extends Component { onSliderChange(slider, value) { console.log('value', value); } render() { return ( <x-slider
onChange={this.onSliderChange.bind(this)}/>
) } }
Ext.create({ xtype: 'slider', listeners: {
change: this.onSliderChange }});
Component Refs
• As with DOM elements, you can access Ext components by adding a “ref” prop.
• Here this.refs.slider is an instance of Ext.slider.Slider
import React, { Component } from 'react'; class MyComponent extends Component { onSliderChange(slider, value) { console.log('value', this.refs.slider.getValue()); } render() { return ( <x-slider
ref="slider" onChange={this.onSliderChange.bind(this)}
/> ) } }
More Complex Configs
• It’s all just JavaScript.
• React props => Ext JS configs
class MyComponent extends Component { render() { return ( <x-grid plugins={[ { type: 'columnresizing' } ]} columns={[ { text: 'Name', dataIndex: 'name' }, { text: 'Email', dataIndex: 'email' } ]} store={{ data: [ ...
] }} /> ) } }
Layouts
• Work like you’d expect
class MyComponent extends Component { render() { return ( <x-container layout="hbox"> <x-button text="Left"/> <x-button text="Right"/> </x-container> ) } }
Layouts
• Work like you’d expect
class MyComponent extends Component { render() { return ( <x-container layout="hbox"> <x-button text="Left"/> <x-button text="Right"/> </x-container> ) } }
Ext.create({ xtype: 'container', layout: 'hbox', items: [ { xtype: 'button', text: 'Left' }, { xtype: 'button', text: 'Right' } ]});
Updates
• When a prop changes, @extjs/reactor automatically calls the corresponding setter method to update your component’s configs.
class MyComponent extends Component {
constructor(props) { super(props); this.state = { dirty: true }; } render() { const text = this.state.dirty ? "Save Changes" : "Changes Saved"; return ( <x-button text={text} handler={this.onClick.bind(this)} /> ) } onClick() { this.setState({ dirty: false }); }
}
Updates
• When a prop changes, @extjs/reactor automatically calls the corresponding setter method to update your component’s configs.
class MyComponent extends Component {
constructor(props) { super(props); this.state = { dirty: true }; } render() { const text = this.state.dirty ? "Save Changes" : "Changes Saved"; return ( <x-button text={text} handler={this.onClick.bind(this)} /> ) } onClick() { this.setState({ dirty: false }); }
}
button.setText(text);
Summing Up
props configs
on/A-Z/ listeners
child elements items: []
updates setter calls
@extjs/reactor-webpack-plugin
Setting up your React app for Ext JS
ext-all.js reactor-webpack-plugin
Automatic Usage Detectionimport React, { Component } from 'react'; Ext.require('Ext.window.Toast'); export default class MyDialog extends Component { constructor(props) { super(props); this.store = Ext.create('Ext.data.Store', { ... }); } render ( <x-window> <x-grid ... /> </x-window> ) }
ext.js
ext.css
Configure Theme, Toolkit, and Packages
const ExtJSReactorWebpackPlugin = require('@extjs/reactor-webpack-plugin'); module.exports = { ... plugins: [ new ExtJSReactorWebpackPlugin({ sdk: 'ext', // relative or full path to Ext JS SDK toolkit: 'modern', theme: 'theme-material', packages: ['charts'], output: path.join('build', 'ext') }) ] ... };
@extjs/reactor-boilerplate
reactor-boilerplate