Modern Javascript
React + Redux
Agenda
To explain tools to use for developing a robust, performant and maintainable web application.
Pavithra Kodmad
@pkodmad
Evolution of Front end practices.
MVC
- Controller/View/Service
- Broadcast/Emit
- Model structures
Modern Javascript
- React View
- Redux for maintaining state
- Bundling with Webpack
React.js
- Open sourced by Facebook
- Built/Maintained by the community
Features
- UI Declarative Framework
- Virtual DOM
- Component Structure
- Data down approach
Declarative
How vs What?
//Imperative
var sum = 0;
for(var i=0;i< 5; i++){
sum +=i;
}
return sum;
//Declarative
[0,1,2,3,4].reduce(function(cur, agg){
agg += cur;
return agg;
}, 0)
Components
- Has a Lifecycle
- Renders itself (JSX)
- Receives props
- Maintains state
export const MyComponent = React.createClass({
render: function(){
var props = this.props
return <div>My Component {props.myprop}</div>
},
componentWillMount: function(){
//Before mount
},
componentWillUnMount: function(){
//Before unmount
},
...
})
<MyComponent myprop={someprops}></MyComponent>
Initial Render
===============
getDefaultProps()
getInitialState()
componentWillMount()
render()
componentDidMount()
Props change
===============
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
State change
===============
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
Unmount
===============
componentWillUnmount()
Virtual DOM
React class vs element
Data Down approach
- Two way data binding sucks
- Manage state declaratively
To scale
var User = React.createClass({
render(){
return <div>
<UserPicture url={this.props.url}></UserPicture>
<UserTag details={this.props.details}></UserTag>
</div>
}
})
var UserPicture = React.createClass({
render(){
return <img src={this.props.url}></img>
}
})
Flux
Lets Flux
Cons of Flux implementations
- State composition was hard
- Event emitter to multiple stores not maintainable
Redux
Change from Flux
- No event emitter
- Single state container
- Recommends Immutable state
State Container
var state = {
orderList:[],
incidentList:[],
selectedOrder:null
}
Reducer(No mutation)
(state, action) => newState
function counter(state, action){
...
return newState
}
appState = {
past:[{s1, a1}, {s2,a2}, {s3,a3}]
current: {s4,a4},
future:[]
}
Actions
var actionObject = {
type:'ACTION_TYPE',
data:dataToChange
}
dispatch(actionObject)
onClick(){
var clickAction = {
type:'CLICK_ACTION',
data:'clicked'
}
dispatch(clickAction)
}
Store
var store = {
state<priv>: <state container>,
getState: return state,
subscribe: <subscribe to state change .returns unsubscribe function>,
dispatch: <dispatch actions>,
reducer<priv>: <root reducer>
}
import {createStore} from 'redux'
//ES6 imports
createStore(reducer, initialState)
import {createStore} from 'redux';
function counter(state = 0, action){
if(action.type === 'INCREMENT'){
return state + 1;
} else if(action.type === 'DECREMENT'){
return state - 1;
} else {
return state;
}
}
var store = createStore(state, initialState)
var nextcounter = counter(0, {type:'INCREMENT'});
//nextcounter = 1;
nextCounter = counter(nextCounter, {type:'INCREMENT'});
//nextCounter = 2;
nextCounter = counter(nextCounter, {type:'somethingelse'});
//nextCounter = 2;
nextCounter = counter(nextCounter, {type:'DECREMENT'});
//nextCounter = 1;
import {createStore} from 'redux';
function counter(state = 0, action){
if(action.type === 'INCREMENT'){
return state + 1;
} else if(action.type === 'DECREMENT'){
return state - 1;
} else {
return state;
}
}
var store = createStore(counter, initialState)
function render(){
ReactDOM.render(<Counter counter={store.getState()} dispatch={store.dispatch}/>, document.getElementById('root'))
}
store.subscribe(render())
var Counter = React.createClass({
render: function(){
var {counter, dispatch} = this.props;
<div>
<div>
{counter}
</div>
<button onClick={dispatch({type:'INCREMENT'})}>INCREMENT</button>
<button onClick={dispatch({type:'DECREMENT'})}>DECREMENT</button>
</div>
}
})
Using redux
- react-redux
- ngRedux
- backbone-redux
- ember-redux
react-redux
- Provider (https://facebook.github.io/react/docs/context.html)
- connect([...],[...])(Component)
import {createStore, combineReducers} from 'redux'
import {Provider} from 'react-redux'
import {reducer1, reducer2} from '../reducers'
import App from '../App'
var rootReducer = combineReducers(reducer1, reducer2);
var store = createStore(rootReducer,{});
<Provider store='store'>
<App/>
</Provider>
//uses React context
//App.js
import {connect} from 'react-redux'
import appAction from '../appAction'
var App = React.createClass({
render(){
return <div>This is the app showing {this.props.filteredState}</div>
}
})
function mapStateToProps(state){
return filteredState; //{substate1, substate2}
}
export default connect(mapStateToProps, {appAction})(App)
When to Redux?
- Deep parent child relationships
- Sibling components trying to communicate
- Aggregator components like Notifications
Learn Redux
M
By Pavithra Kodmad
M
- 1,212