Upload
trayan-iliev
View
315
Download
1
Embed Size (px)
Citation preview
Using Context, Higher-Order Components and Observables with React
Slide 1Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
SofiaMay 15, 2017
Context, HOCs & Observables with React
Trayan Iliev
IPT – Intellectual Products & Technologiese-mail: [email protected]
web: http://www.iproduct.org
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 2Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
About Us: IPT - Intellectual Products & Technologies
Since 2003 we provide trainings and share knowledge in JS/ TypeScript/ Node/ Express/ Socket.IO/ NoSQL/ Angular/ React / Java SE/ EE/ Web/ REST SOA:
Node.js + Express/ hapi + React.js + Redux + GraphQL
Angular + TypeScript + Redux (ngrx)
Java EE6/7, Spring, JSF, Portals/Portlets: Liferay, GateIn
Reactive IoT with Reactor / RxJava / RxJS
SOA & Distributed Hypermedia APIs (REST)
Domain Driven Design & Reactive Microservices
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 3Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Where is The Code?
React.js demo code is available @GitHub:https://github.com/iproduct/demos-and-presentations
Demos:react-router-redux-demo – React + Redux + Router + Thunk (async actions) integrationreact-hocs-observables – React + Redux + Router + RxJS Observables (async action stream transforms) + Reselect + Recompose + Material-UI
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 4Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Contemporary Web Applications
Provide better User Experience (UX) by:
more interactive
loading and reacting faster in response (or even anticipation) of user's moves
able to work offline
supporting multiple devices and screen resolutions (responsive design)
are following design metaphors consistently (e.g. Google Material Design - MD)
looking more like desktop application than static web page
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 5Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
MVC Comes in Different Flavors
MVC
MVVM
MVP
Sources:https://en.wikipedia.org/wiki/Model_View_ViewModel#/media/File:MVVMPattern.png, https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter#/media/File:Model_View_Presenter_GUI_Design_Pattern.pngLicense: CC BY-SA 3.0, Authors:Ugaya40, Daniel.Cardenas
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 6Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Single Page Applications (SPA)
Source: http://stackoverflow.com/questions/12863663/complex-nesting-of-partials-and-templatesAuthor: PhillipKregg
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 7Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
SPA with Multiple Router Outlets
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 8Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Why SPA?
Page does not flicker – seamless (or even animated) transitions
Less data transferred – responses are cached
Only raw data, not markup
Features can be loaded on demand (lazy) or in background
Most page processing happens on the client offloading the server: REST data services + snapshops for crawlers (SEO)
Code reuse – REST endopints are general purpose
Supporting multiple platforms (Web, iOS, Android) → React Native
Using Context, Higher-Order Components and Observables with React
Slide 9Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
SofiaMay 15, 2017
Developing Sinagle Page Apps (SPA) in 3 steps
1) Setting up a build system – npm, webpack, gulp are common choices, babel, typescript, JSX, CSS preprocessors (SASS, SCSS, LESS, PostCSS), servers ...
2) Designing front-end architecture components – views & layouts + view models (presentation data models) + presentation logic (event handling, messaging) + routing paths (essential for SPA)
Better to use component model to boost productivity and maintainability.
3) End-to-end application design – front-end: wireframes → views,data entities & data streams → service API and models design,sitemap → router config
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 10Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Components Resuability - Two Approaches
Inheritance - we create new component Types (or Classes) by extending exiting ones – Class Hierachy:
Composition:
Object composition
Functional composition
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 11Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Object Composition Hierachy
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 12Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Functional Composition
Functional programming (FP) - the mathematical notion of function composition
Composing functions f and g, g(f(x)) means f’s out → g’s input
In FP, the inputs and outputs are values without life cycles
Simpler to understand compared to object compositions
If input-output types match, functions can always compose!
More sophisticated forms of composition can be implemented using higher-order functions: functions can be passed as inputs and received as outputs to/from other functions
Functions are just immutable values – no special treatment!
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 13Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Higher-Order Components
Higher-order component (HOC) is a function that takes a component and returns a new component:
const EnhancedComponent =
higherOrderComponent( WrappedComponent );
Example:
const VisibleTodoList = connect(mapStateToProps, mapDispatchToProps) (TodoList);
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 14Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Use HOCs For Cross-Cutting Concernsclass BlogPost extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = { blogPost: DataSource.getBlogPost(props.id) }; } componentDidMount(){DataSource.addChangeListener(this.handleChange);} componentWillUnmount() { DataSource.removeChangeListener(this.handleChange);} handleChange() { this.setState({blogPost: DataSource.getBlogPost(this.props.id)}); } render() { return <TextBlock text={this.state.blogPost} />; }}
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 15Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Use HOCs For Cross-Cutting Concerns (2)function withSubscription(WrappedComponent, selectData) { return class extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = {data: selectData(DataSource, props) }; } componentDidMount() { DataSource.addChangeListener(this.handleChange); } componentWillUnmount({ DataSource.removeChangeListener(this.handleChange);} handleChange() { this.setState({data: selectData(DataSource, this.props)});} render() { return <WrappedComponent data={this.state.data} {...this.props}/>;} };}
Anonimous class.Name should be added using dispalyName static property
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 16Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Usage:
const CommentListWithSubscription = withSubscription(
CommentList,
(DataSource) => DataSource.getComments()
);
const BlogPostWithSubscription = withSubscription(
BlogPost,
(DataSource, props) => DataSource.getBlogPost(props.id)
});
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 17Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Using HOCs – Things To Remember:
Don't Mutate the Original Component. Use Composition.
Convention: Pass Unrelated Props Through to the Wrapped Component
Convention: Maximizing Composabilityconst ConnectedComment = connect(commentSelector, commentActions)(Comment);
// compose(f, g, h) is the same as (...args) => f(g(h(...args)))const enhance = compose(withRouter, connect(commentSelector, commentActions) );enhance(Comment);
Convention: Wrap the Display Name for Easy Debugging
The order matters!
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 18Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
How to Boost Performance with React
Use the production build
Avoiding reconciling the DOM – React provides a component lifecycle function, shouldComponentUpdate, which is triggered before the re-rendering process starts (virtual DOM comparison and possible eventual DOM reconciliation), giving the developer the ability to short circuit this process. Default:
shouldComponentUpdate: function(nextProps, nextState) { return true; }
React invokes shouldComponentUpdate often -should be fast
Use immutability for comparisons to be efficient
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 19Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Performance with shouldComponentUpdate
class MyStatelessComp extends React.Component { static propTypes = { value: PropTypes.string.isRequired };
shouldComponentUpdate: function(nextProps, nextState) { return this.props.value !== nextProps.value; },
render: function() { return <div>{this.props.value}</div>; }});
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 20Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Boosting Performance: PureRenderMixin
Before – using mixins(Mixins Considered Harmful by Dan Abramov):
var PureRenderMixin = require('react-addons-pure-render-mixin');React.createClass({ mixins: [PureRenderMixin],
render: function() { return <div className={this.props.className}>foo</div>; }});
Now you should prefer:class MyComponent extends React.PureComponent { … }
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 21Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Using HOCs – Caveats:
Don't Use HOCs Inside the render Method:render() { const EnhancedComponent = enhance(MyComponent); return <EnhancedComponent />;}
Static Methods Must Be Copied Over
Maximizing Composability
Refs Aren't Passed Through
Don't
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 22Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Refs to Components
Refs (references) – allow to find the DOM markup rendered by a component, and invoke methods on component instances returned from render()
Example uses: absolute positioning, using React components in larger non-React applications, transition existing code to React.
var myComponentInstanceRef = ReactDOM.render(<MyComp />, myContainer); myComponentInstanceRef.doSomething();
ReactDOM.findDOMNode(componentInstance) – this function will return the DOM node belonging to the outermost HTML element returned by render.
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 23Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
The ref Callback Attributerender: function() { return ( <TextInput ref={ function(input) { if (input != null) { input.focus(); } }} /> );},
OR better using ES6 => :render: function() { return <TextInput ref={(c) => this._input = c} />;},componentDidMount: function() { this._input.focus();},
Will be called twice – on mount with ref, and on unmount with null. That is why
we check if ref not null.
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 24Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Using React Component Context
React props allow to track data-flow easy between componets
React Context is alternative if you want to pass data through the component tree without having to pass the props down manually at every level.
Inversion of Control (IoC) principle and Dependency Injection (DI) pattern
React's "context" feature lets you do this – Example how to inject testService and router in TestsList component:
TestsList.contextTypes = { testService: React.PropTypes.object, router: React.PropTypes.object };
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 25Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Passing Refs from Wrapped Comp to HOC
function Field({ inputRef, ...rest }) { return <input ref={inputRef} {...rest} />;}
// Wrap Field in a higher-order componentconst EnhancedField = enhance(Field);
// Inside a class component's render method...<EnhancedField inputRef={(inputEl) => { // This callback gets passed through as a regular prop this.inputEl = inputEl }}/>
// Now you can call imperative methodsthis.inputEl.focus();
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 26Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Providing Services with React Contextclass IPTKnowledgeTester extends React.Component { constructor(props) { super(props); this.testServiceSingleton = new TestService(TEST_SERVICE_URL); this.localeServiceSingleton = new LocaleService(DEFAULT_LOCALE, this.onLocaleChange); } getChildContext() { return { testService: this.testServiceSingleton, localeService: this.localeServiceSingleton }; } …}
IPTKnowledgeTester.childContextTypes = { testService: React.PropTypes.object, localeService: React.PropTypes.object};
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 27Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
React Context Usage Example
handleAddTest() {
const path = { pathname: '/test',
query: { controls: true, edit: true } };
this.context.router.push(path);
}
componentDidMount() {
this.context.testService.getTests().then((tests) => {
this.setState({ tests: tests });
});
}
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 28Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Referencing Context in Lifecycle Methods
void componentWillReceiveProps( object nextProps, object nextContext)
boolean shouldComponentUpdate( object nextProps, object nextState, object nextContext)
void componentWillUpdate( object nextProps, object nextState, object nextContext)
void componentDidUpdate( object prevProps, object prevState, object prevContext)
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 29Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Using Context with Functional Components
const Button = ({children}, context) =>
<button style={{background: context.color}}>
{children}
</button>;
Button.contextTypes = {color: React.PropTypes.string};
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 30Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
React Router v4 Configuration
<Route path="/" component={Base} /><Route path="/home" component={Home} /><Route path="/intro" render={() => <div>How to start using this app</div>} /><Route path="/repos" component={Repos} /><Route path="/topics" component={Topics} /><Route path="/about" component={About} /><Route path="/show-location" component={ShowTheLocation} />
const Repos = (props) => { return ( <div> <h2>Repos</h2> <Route path="/repos/:userName/:repoName" component={Repo} /> </div> );};
Hierarchical navigation, no need to use props.children
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 31Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Site Navigation using Router v4
<ul className="main-menu"> <li><Link to="/home">Home</Link></li> <li><Link to="/intro">Intro</Link></li> <li><Link to="/repos">Repos</Link></li> <li><Link to="/topics">Topics</Link></li> <li><Link to="/show-location">Show the Location</Link></li> <li><Link to="/about">About</Link></li> <form className="navbar-form navbar-right" role="search" onSubmit={this.handleSerch}> <input type="text" placeholder="userName" /> / {' '} <input type="text" placeholder="repo" /> {' '} <button type="submit" className="btn btn-default">Go</button> </form></ul>
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 32Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Programmatic Navigation using Router v4
ReactDOM.render( <Router > <App /> </Router>, document.getElementById('root'));
handleSerch = (event) => { event.preventDefault(); const userName = event.target.elements[0].value; const repo = event.target.elements[1].value; const path = `/repos/${userName}/${repo}`; console.log(path); console.log(this.context); // this.context.router.history.push(path); this.props.history.push(path); }
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 33Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Using @withRouter Decorator (HOC) - Router v4
import React from 'react';import PropTypes from 'prop-types';import { withRouter } from 'react-router-dom';
@withRouterexport default class ShowTheLocation extends React.Component { render() { const { match, location, history } = this.props; return ( <div> <div>You are now at {location.pathname}</div> <div>The match is: {JSON.stringify(match)}</div> <div>The history contains: {JSON.stringify(history)}</div> </div> ) }}
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 34Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Flux Design Pattern
Source: Flux in GitHub, https://github.com/facebook/flux, License: BSD 3-clause "New" License
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 35Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Redux Design Pattern
Source: @ngrx/store in GitHub, https://gist.github.com/btroncone/a6e4347326749f938510
Linear flow:
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 36Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Redux
Streamlined state management for React.js applications, inspired by Redux
State is a single immutable data structure
Actions describe state changes
Pure functions called reducers take the previous state and the next action to compute the new state
State is kept within single Store, and accessed through sub-state selectors, or as Observable of state changes
Components are by default perfomance optimized using the shouldComponentUpdate() → performant change detection
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 37Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Redux Recommended (Basic) Project Structure
actions – action creator factory functions (design pattern Command)
assets – static assets (css images, fonts, etc.) folder
components – simple (dumb) react components – pure render
container – Redux Store aware (smart) component wrappers
reducers – the only way to advance state:
function(OldStoreState, Action) => NewStoreState // = Rx scan()
index.js – bootstraps app providing access to Store for all containers (smart components) using React context
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 38Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Bootstrapping Redux App – index.js
import React from 'react';import ReactDOM from 'react-dom';import { Provider } from 'react-redux';import { createStore } from 'redux';import rootReducer from './reducers';import { FilteredTodoApp } from './containers/filtered-todo-app';const store = createStore( rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() );const render = (Component) => { ReactDOM.render( <Provider store={store}> <FilteredTodoApp /> </Provider>, document.getElementById('root') );};
Top level container componentRedux store provider
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 39Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Redux Action Creators – /actions/index.js
let nextTodoId = 0;export const addTodo = (text) => ({ type: 'ADD_TODO', id: nextTodoId++, text});export const setVisibilityFilter = (filter) => ({ type: 'SET_VISIBILITY_FILTER', filter});export const changeStatus = (id, status) => ({ type: 'CHANGE_STATUS', id, status});...
Action PayloadAction Type
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 40Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Redux Reducers – /reducers/todo.js
const todoReducer = (state = {}, action) => { switch (action.type) { case 'ADD_TODO': return { id: action.id, text: action.text, status: 'active' }; case 'CHANGE_STATUS': if (state.id !== action.id) { return state; } return Object.assign({}, state, { status: action.status }); default: return state; }};
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 41Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Redux Reducers – /reducers/todos.js
const todosReducer = (state = [], action) => { switch (action.type) { case 'ADD_TODO': return [ ...state, todoReducer(undefined, action) ]; case 'CHANGE_STATUS': return state.map(todo => todoReducer(todo, action) ); case 'DELETE_TODOS': return state.filter(todo => todo.status !== action.status ); default: return state; }};
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 42Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Redux Root Reducer – /reducers/index.js
import { combineReducers } from 'redux';import todos from './todos';import visibilityFilter from './visibilityFilter';
const rootReducer = combineReducers({ todos, visibilityFilter});
export default rootReducer;
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 43Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Redux Containers – /conatiners/visible-todo-list.js
const getVisibleTodos = (todos, filter) => todos.filter( todo => filter === 'all' ? true: todo.status === filter);const mapStateToProps = (state) => ({ todos: getVisibleTodos(state.todos, state.visibilityFilter)});const mapDispatchToProps = (dispatch) => ({ onCompleted: (id) => { dispatch(changeStatus(id, 'completed')); }, onCanceled: (id) => { dispatch(changeStatus(id, 'canceled')); }});const VisibleTodoList = connect(mapStateToProps, mapDispatchToProps) (TodoList);export default VisibleTodoList;
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 44Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Redux App using ES7 @connect Decorator
const getVisibleTodos = (todos, filter) => todos.filter( todo => filter === 'all' ? true: todo.status === filter);const mapStateToProps = (state) => ({ todos: getVisibleTodos(state.todos, state.visibilityFilter)});const mapDispatchToProps = (dispatch) => ({ onCompleted: (id) => { dispatch(changeStatus(id, 'completed')); }, onCanceled: (id) => { dispatch(changeStatus(id, 'canceled')); }});@connect(mapStateToProps, mapDispatchToProps)export default class TodoList extends React.Component { constructor(props) { ...
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 45Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Using Redux Router Redux and Redux Thunk (1)
Idea: history + store (redux) → react-router-redux → enhanced history → react-router
import { compose, createStore, combineReducers, applyMiddleware } from 'redux';import { Provider } from 'react-redux';import createHistory from 'history/createBrowserHistory';import { ConnectedRouter, routerReducer, routerMiddleware, push } from 'react-router-redux'; // React Router to Redux integrationimport thunk from 'redux-thunk'; // Allows using thunks = async actionsimport reducers from './reducers'; // your reducers hereconst history = createHistory(); // use browser History API// middleware for intercepting & dispatching navigation & async actionsconst middleware = [routerMiddleware(history), thunk];// Enable Redux Devtoolsconst composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 46Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Using Redux Router Redux and Redux Thunk (2)
const store = createStore( CombineReducers({ ...reducers, router: routerReducer // Add the reducer to store on `router` key }), /* preloadedState, */ ComposeEnhancers( applyMiddleware(...middleware) ));
store.dispatch(push('/repos/react/redux'));//dispatch navigation action
ReactDOM.render( <Provider store={store}>//ConnectedRouter use store from the Provider <ConnectedRouter history={history}> <App /> </ConnectedRouter> </Provider>, document.getElementById('root'))
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 47Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Redux Thunk Async Actions - /actions/counter.js
export function increment(x) { return { type: INCREMENT, amount: x }}
export function incrementAsync(x) { return dispatch => //Can invoke sync or async actions with `dispatch` setTimeout(() => { dispatch(increment(x)); }, 2000); }
export function incrementIfOdd(x) { return (dispatch, getState) => { const { counter } = getState(); if (counter.number % 2 === 0) return; dispatch(increment(x)); //Can invoke actions conditionally };}
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 48Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Advanced Redux using Middleware Libraries
Normalizr – normalizing and denormalizing data in state, helps to transform nested JSON response structures into a relational DB-like plain entities, referenced by Id in the Redux store.
redux-thunk – in addition to plain actions, Action Creators can now return Thunks – callback functions of dispatch and getState arguments, allowing to handle async operations like data fetch from REST endpoint and Promise-like composition.
redux-promise/ redux-promise-middleware – thunk alternatives
redux-observable – really powerfull reactive transforms of async action events as RxJS Observables, called Epics:
(action$:Observable<Action>, store:Store) => Observable<Action>
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 49Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Functional Reactive Programming
Functional Reactive Programming (FRP) [Wikipedia]: a programming paradigm for reactive programming (asynchronous dataflow programming) using the building blocks of functional programming (e.g. map, reduce, filter). FRP has been used for programming graphical user interfaces (GUIs), robotics, and music, aiming to simplify these problems by explicitly modeling time. Ex. (RxJS):
const Observable = require('rxjs').Observable;Observable.from(['Reactive', 'Extensions', 'JavaScript']) .take(2).map(s => `${s}: on ${new Date()}`) .subscribe(s => console.log(s));
Result: Reactive: on Sat Apr 29 2017 20:00:39 GMT+0300 Extensions: on Sat Apr 29 2017 20:00:39 GMT+0300
Good intro tutorial in RP using RxJS by Andre Staltz see: https://gist.github.com/staltz/868e7e9bc2a7b8c1f754JS Fiddle of the demo: http://jsfiddle.net/staltz/8jFJH/48/
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 50Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Definitions of Reactive Programming
Microsoft® opens source polyglot project ReactiveX (Reactive Extensions) [http://reactivex.io]:
Rx = Observables + LINQ + Schedulers :)Supported Languages – Java: RxJava, JavaScript: RxJS, C#: Rx.NET, C#(Unity): UniRx, Scala: RxScala, Clojure: RxClojure, C++: RxCpp, Ruby: Rx.rb, Python: RxPY, Groovy: RxGroovy, JRuby: RxJRuby, Kotlin: RxKotlin, Swift: RxSwiftReactiveX for platforms and frameworks: RxNetty, RxAndroid, RxCocoa
Reactive Streams Specification [http://www.reactive-streams.org/]
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 51Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
RxJS – JS ReactiveX (Reactive Extensions)[http://reactivex.io, https://github.com/ReactiveX]
ReactiveX is a polyglot library for composing asynchronous event streams (observable sequences).It extends the observer pattern by declarative composition of functional transformations on events streams (e.g. map-filter-reduce, etc.) Abstracs away low-level concerns like concurrency, synchronization, and non-blocking I/O.Follows the next - error - completed event flowAllows natural implementation of Redux design patternAlternative (together with promises) for solving “callback hell” problem
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 52Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Resources: RxMarbles and RxJS Coans
RxMarbles:
http://rxmarbles.com/
RxJS Coans:https://github.com/Reactive-Extensions/RxJSKoans
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 53Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Demo Time :)
React.js demo code is available @GitHub:https://github.com/iproduct/demos-and-presentations
Demos:react-router-redux-demo – React + Redux + Router + Thunk (async actions) integrationreact-hocs-observables – React + Redux + Router + RxJS Observables (async action stream transforms) + Reselect + Recompose + Material-UI
Using Context, Higher-Order Components and Observables with React
SofiaMay 15, 2017
Slide 54Sources:ReactJS [https://github.com/facebook/react/ ] Licensed under the Creative Commons Attribution 4.0 International Public License
Thank’s for Your Attention!
Trayan Iliev
CEO of IPT – Intellectual Products & Technologies
http://iproduct.org/
http://robolearn.org/
https://github.com/iproduct
https://twitter.com/trayaniliev
https://www.facebook.com/IPT.EACAD
https://plus.google.com/+IproductOrg