SlideShare ist ein Scribd-Unternehmen logo
1 von 37
Downloaden Sie, um offline zu lesen
redux vs alt
@uldissturms
objectives
compare redux and alt:
• concepts
• testing
• trends
agenda
• why?
• react
• flux
• redux and alt comparison
• microservices for client side
why?
quality takes time
quality
time
fb contact list
react
• just the UI
• virtual DOM
• one way data flow
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
ReactDOM.render(<HelloMessage name="John" />, mountNode); Hello John
fb chat
flux
Flux is the application architecture that Facebook uses for building client-side web
applications. It complements React and is more of a pattern than a framework.
redux and alt
• implementations of flux
• isomorphic - (equal shape when rendered both on client and server
side)
• support react-native
redux
• whole state of app is stored in an object tree inside a single store
• only way to change the state tree is to emit an action, an object
describing what happened
• to specify how the actions transform the state tree, you write pure
reducers
• great documentation - not that it needs one really
predictable state container for JavaScript apps
alt
• pure flux
• *actively* maintained
• extremely flexible and *unopinionated* in how you use flux
• has logo
• lacks up to date documentation and samples
Isomorphic flux implementation
hello world
!"" app.jsx
!"" components
#   !"" greet.jsx
#   !"" hello.jsx
#   !"" hello.test.js
#   $"" helloList.jsx
!"" index.html
!"" index.js
!"" state
#   !"" namesReducer.js
#   !"" namesReducer.test.js
#   $"" store.js
!"" actions
#   $"" NamesActions.js
!"" alt.js
!"" components
#   !"" greet.jsx
#   !"" hello.jsx
#   !"" hello.test.js
#   $"" helloList.jsx
!"" index.html
!"" index.js
!"" state
#   !"" configureNamesStore.js
#   !"" configureNamesStore.test.js
#   $"" namesStore.js
components
• similar or equal setup for tiny components
• differs for larger components that contain actions and more logic
• testing is easy using react test utils or wrapper libraries
• redux - allows function syntax, alt - can get messy when static
functions needed
components - code
import React from 'react';
const Hello = ({name}) => {
return (
<div>
Hello, <b class='test-name'>{name}</b>
</div>
);
};
export default Hello;
components - tests
describe('hello component', () => {
it('renders name', () => {
const output = renderHello('Steve');
const name = getChildrenByClass(output, 'test-name');
expect(name.props.children).toEqual('Steve');
});
it('renders component', () => {
const output = renderHello('Steve');
const expected =
<div>Hello, <b class="test-name">Steve</b></div>;
expect(output).toEqualJSX(expected);
});
});
const renderHello = name => {
const renderer = TestUtils.createRenderer();
renderer.render(<Hello name={name}/>);
return renderer.getRenderOutput();
}
components - tests
describe('<MyComponent />', () => {
it('renders three <Foo /> components', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper.find(Foo)).to.have.length(3);
});
it('renders an `.icon-star`', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper.find('.icon-star')).to.have.length(1);
});
it('renders children when passed in', () => {
const wrapper = shallow(
<MyComponent>
<div className="unique" />
</MyComponent>
);
expect(wrapper.contains(<div className="unique" />)).to.equal(true);
});
it('simulates click events', () => {
const onButtonClick = sinon.spy();
const wrapper = shallow(
<Foo onButtonClick={onButtonClick} />
);
wrapper.find('button').simulate('click');
expect(onButtonClick.calledOnce).to.equal(true);
});
});
airbnb/enzyme
react element
css class
html element
simulate event
stores
• redux - one, alt - many
• redux - registers reducers, alt - defines logic to execute based on data
passed by action
• redux - no tests needed, test reducers, alt - the meat of logic, harder to test
without side effects
• redux - immutable, alt - mutable
• alt - ReferenceError: A store named NamesStore already exists, double
check your store names or pass in your own custom identifier for each store]
stores - code
import alt from '../alt';
import namesActions from '../actions/NamesActions';
class NamesStore {
constructor() {
this.bindListeners({ add: namesActions.ADD})
this.state = {
names: []
}
}
add(name) {
if (name === 'Stranger') {
return this.state;
}
this.setState({ names: [...this.state.names, name] });
}
}
export default function configureStore() {
return alt.createStore(NamesStore, 'NamesStore');
}
stores - tests
import alt from '../alt';
import configureStore from './configureNamesStore';
import namesActions from '../actions/NamesActions';
const greet = name => {
const action = namesActions.ADD;
const data = name;
alt.dispatcher.dispatch({ action, data });
};
describe('store', () => {
it('starts off with empty names array', () => {
const store = configureStore();
const state = store.getState();
expect(state).toEqual({ names: []});
});
it('adds a name after greet action processed', () => {
const store = configureStore();
greet('Steve');
const state = store.getState();
expect(state).toEqual({ names: ['Steve']});
});
});
reducers
• pure functions - zero side-effects, only rely on parameter values
• super easy to test
• they scale - easy to add a new one
reducers - code
const shouldGreet = name => {
return name !== 'Stranger';
};
const namesReducer = (state = { names: [] }, action) => {
if (action.type === 'GREET' && shouldGreet(action.payload.name)) {
return { names: [...state.names, action.payload.name] };
}
return state;
};
export default namesReducer;
reducers - tests
import expect from 'expect';
import namesReducer from './namesReducer';
const greet = name => {
return { type: 'GREET', payload: { name: name }};
};
describe('names reducer', () => {
it('greets', () => {
const state = namesReducer({ names: [] }, greet('Steve'));
expect(state).toEqual({ names: ['Steve']});
});
it('no greetings to Stranger', () => {
const state = namesReducer({ names: [] }, greet('Stranger'));
expect(state).toEqual({ names: []});
});
});
react-redux glue
const store = configureStore();
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('App')
)
1
react-redux glue
import React from 'react';
import {connect} from 'react-redux';
import Hello from './hello';
const HelloList = ({ names }) => {
return (<div className='test-hello-name-list'>
{names.map(name =>
<Hello name={name}/>
)}
</div>);
}
const mapStateToProps = state => {
return {
names: state.names
}
}
export default connect(mapStateToProps)(HelloList);
2
react-alt glue
// Bad: getting into lib internals
import connectToStores from 'alt-utils/lib/connectToStores';
class HelloList extends React.Component {
static getStores(props) {
return [store];
}
static getPropsFromStores(props) {
return store.getState();
}
render() {
return (
<div className='test-hello-name-list'>
{this.props.names.map(name =>
<Hello name={name}/>
) }
</div>
);
}
}
export default connectToStores(HelloList);
1
react-alt glueclass Greet extends React.Component {
constructor(props) {
super(props);
this.submit = this.submit.bind(this);
}
static getStores(props) {
return [store]
}
static getPropsFromStores(props) {
return store.getState();
}
submit(e) {
e.preventDefault();
namesActions.add(this.input.value);
}
render() {
return (
<div className='test-greet'>
<form onSubmit={this.submit}>
<input id='test-greeting' type='text' ref={node => {
this.input = node}}/>
<button id='test-submit-greeting' type='submit'>Greet</button>
</form>
</div>
);
}
};
export default connectToStores(Greet);
1
application stats
35 ./hello-alt/components/greet.jsx
11 ./hello-alt/components/hello.jsx
32 ./hello-alt/components/hello.test.js
25 ./hello-alt/components/helloList.jsx
20 ./hello-alt/state/configureNamesStore.js
24 ./hello-alt/state/configureNamesStore.test.js
2 ./hello-alt/state/namesStore.js
8 ./hello-alt/actions/NamesActions.js
4 ./hello-alt/alt.js
12 ./hello-alt/index.js
21 ./hello-redux/components/greet.jsx
11 ./hello-redux/components/hello.jsx
32 ./hello-redux/components/hello.test.js
12 ./hello-redux/components/helloList.jsx
6 ./hello-redux/state/store.js
12 ./hello-redux/state/namesReducer.js
17 ./hello-redux/state/namesReducer.test.js
19 ./hello-redux/app.jsx
14 ./hello-redux/index.js
lines of code
144 total 173 total = 20 % more
scaling application
react alt
store
reducer
reducer
reducer
store
store
store
stats
redux alt
version 3.5.2 0.18.4
size 5.9K (2kb?) 23K
downloads / month 670K 38K
repo reactjs/redux goatslacker/alt
open issues 44 79
pull requests 20 4
last commit hours ago almost a month ago
comparison
redux alt
Open Systems Don't Always Win - Steve Jobs
verdict
TRIAL
Redux is a great, mature tool that has helped many of our teams reframe how they
think about managing state in client-side apps. Using a Flux-style approach, it enables
a loosely coupled state-machine architecture that's easy to reason about. We've found
it a good companion to some of our favored JavaScript frameworks, such as Ember
and React - ThoughtWorks TechRadar 2016 April
HOLD
Alt although says to be unopinionated it pushes to use action objects, static functions
that are used to connect components to stores, possible to mutate store state and
having multiple stores might encourage a monolith approach, doesn’t have as big
community backing as Redux and feels dated in comparison
end to end tests
var process = require('process');
var port = process.env.PORT;
function navigateToSite(test) {
return test.open('http://localhost:' + port);
}
module.exports = {
'says hello': function (test) {
navigateToSite(test)
.assert.doesntExist('.test-name', 'initial state has no greetings')
.type('#test-greeting', 'Steve')
.click('#test-submit-greeting')
.assert.text('.test-hello', 'Hello, Steve', 'adds a new greeting')
.done();
}
};
give confidence when switching frameworks
*don’t use dalekjs
example site - TES Global
microservices
https://www.youtube.com/watch?v=_SoPZS7Wqiw
one way to implement
implementation by TES Global
– Antoine de Saint Exupéry
It seems that perfection is attained, not when there is nothing more
to add, but when there is nothing more to take away
q&a
links
• http://redux.js.org
• http://alt.js.org
• https://github.com/airbnb/enzyme
• https://egghead.io/series/react-testing-cookbook
• https://egghead.io/series/getting-started-with-redux
• http://redux.js.org/docs/recipes/WritingTests.html
• https://github.com/gaearon/redux-devtools
• https://github.com/uldissturms/talks

Weitere ähnliche Inhalte

Was ist angesagt?

React.js or why DOM finally makes sense
React.js or why DOM finally makes senseReact.js or why DOM finally makes sense
React.js or why DOM finally makes sense
Eldar Djafarov
 

Was ist angesagt? (20)

React JS and Redux
React JS and ReduxReact JS and Redux
React JS and Redux
 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux Introduction
 
Better web apps with React and Redux
Better web apps with React and ReduxBetter web apps with React and Redux
Better web apps with React and Redux
 
ReactJs presentation
ReactJs presentationReactJs presentation
ReactJs presentation
 
React & Redux
React & ReduxReact & Redux
React & Redux
 
React / Redux Architectures
React / Redux ArchitecturesReact / Redux Architectures
React / Redux Architectures
 
Getting started with ReactJS
Getting started with ReactJSGetting started with ReactJS
Getting started with ReactJS
 
React js
React jsReact js
React js
 
Introduction to React & Redux
Introduction to React & ReduxIntroduction to React & Redux
Introduction to React & Redux
 
React for Dummies
React for DummiesReact for Dummies
React for Dummies
 
React & Redux
React & ReduxReact & Redux
React & Redux
 
Introduction to react and redux
Introduction to react and reduxIntroduction to react and redux
Introduction to react and redux
 
React redux
React reduxReact redux
React redux
 
React + Redux. Best practices
React + Redux.  Best practicesReact + Redux.  Best practices
React + Redux. Best practices
 
React, Flux and a little bit of Redux
React, Flux and a little bit of ReduxReact, Flux and a little bit of Redux
React, Flux and a little bit of Redux
 
React.js or why DOM finally makes sense
React.js or why DOM finally makes senseReact.js or why DOM finally makes sense
React.js or why DOM finally makes sense
 
Let's Redux!
Let's Redux!Let's Redux!
Let's Redux!
 
ProvJS: Six Months of ReactJS and Redux
ProvJS:  Six Months of ReactJS and ReduxProvJS:  Six Months of ReactJS and Redux
ProvJS: Six Months of ReactJS and Redux
 
React.js and Redux overview
React.js and Redux overviewReact.js and Redux overview
React.js and Redux overview
 
React with Redux
React with ReduxReact with Redux
React with Redux
 

Andere mochten auch

Andere mochten auch (9)

Reducers+flux=redux
Reducers+flux=reduxReducers+flux=redux
Reducers+flux=redux
 
Designing applications with Redux
Designing applications with ReduxDesigning applications with Redux
Designing applications with Redux
 
Flux and redux
Flux and reduxFlux and redux
Flux and redux
 
React. Flux. Redux
React. Flux. ReduxReact. Flux. Redux
React. Flux. Redux
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.
 
005. a React project structure
005. a React project structure005. a React project structure
005. a React project structure
 
NDC 2015 이광영 [야생의 땅: 듀랑고] 전투 시스템 개발 일지
NDC 2015 이광영 [야생의 땅: 듀랑고] 전투 시스템 개발 일지NDC 2015 이광영 [야생의 땅: 듀랑고] 전투 시스템 개발 일지
NDC 2015 이광영 [야생의 땅: 듀랑고] 전투 시스템 개발 일지
 
Building React Applications with Redux
Building React Applications with ReduxBuilding React Applications with Redux
Building React Applications with Redux
 
중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직중앙 서버 없는 게임 로직
중앙 서버 없는 게임 로직
 

Ähnlich wie Redux vs Alt

Ähnlich wie Redux vs Alt (20)

React lecture
React lectureReact lecture
React lecture
 
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
JS Fest 2019. Glenn Reyes. With great power comes great React hooks!
 
Building complex User Interfaces with Sitecore and React
Building complex User Interfaces with Sitecore and ReactBuilding complex User Interfaces with Sitecore and React
Building complex User Interfaces with Sitecore and React
 
React nocojs
React nocojsReact nocojs
React nocojs
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
Dive into React Performance
Dive into React PerformanceDive into React Performance
Dive into React Performance
 
React 101
React 101React 101
React 101
 
Full Stack Toronto - the 3R Stack
Full Stack Toronto - the 3R StackFull Stack Toronto - the 3R Stack
Full Stack Toronto - the 3R Stack
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
React table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilterReact table tutorial project setup, use table, and usefilter
React table tutorial project setup, use table, and usefilter
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Stay with React.js in 2020
Stay with React.js in 2020Stay with React.js in 2020
Stay with React.js in 2020
 
React & Redux for noobs
React & Redux for noobsReact & Redux for noobs
React & Redux for noobs
 
Reactивная тяга
Reactивная тягаReactивная тяга
Reactивная тяга
 
Connect.js - Exploring React.Native
Connect.js - Exploring React.NativeConnect.js - Exploring React.Native
Connect.js - Exploring React.Native
 
Writing testable js [by Ted Piotrowski]
Writing testable js [by Ted Piotrowski]Writing testable js [by Ted Piotrowski]
Writing testable js [by Ted Piotrowski]
 
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptjQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 
React/Redux
React/ReduxReact/Redux
React/Redux
 

Kürzlich hochgeladen

%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 

Kürzlich hochgeladen (20)

%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 

Redux vs Alt

  • 2. objectives compare redux and alt: • concepts • testing • trends
  • 3. agenda • why? • react • flux • redux and alt comparison • microservices for client side
  • 6. react • just the UI • virtual DOM • one way data flow var HelloMessage = React.createClass({ render: function() { return <div>Hello {this.props.name}</div>; } }); ReactDOM.render(<HelloMessage name="John" />, mountNode); Hello John
  • 8. flux Flux is the application architecture that Facebook uses for building client-side web applications. It complements React and is more of a pattern than a framework.
  • 9. redux and alt • implementations of flux • isomorphic - (equal shape when rendered both on client and server side) • support react-native
  • 10. redux • whole state of app is stored in an object tree inside a single store • only way to change the state tree is to emit an action, an object describing what happened • to specify how the actions transform the state tree, you write pure reducers • great documentation - not that it needs one really predictable state container for JavaScript apps
  • 11. alt • pure flux • *actively* maintained • extremely flexible and *unopinionated* in how you use flux • has logo • lacks up to date documentation and samples Isomorphic flux implementation
  • 12. hello world !"" app.jsx !"" components #   !"" greet.jsx #   !"" hello.jsx #   !"" hello.test.js #   $"" helloList.jsx !"" index.html !"" index.js !"" state #   !"" namesReducer.js #   !"" namesReducer.test.js #   $"" store.js !"" actions #   $"" NamesActions.js !"" alt.js !"" components #   !"" greet.jsx #   !"" hello.jsx #   !"" hello.test.js #   $"" helloList.jsx !"" index.html !"" index.js !"" state #   !"" configureNamesStore.js #   !"" configureNamesStore.test.js #   $"" namesStore.js
  • 13. components • similar or equal setup for tiny components • differs for larger components that contain actions and more logic • testing is easy using react test utils or wrapper libraries • redux - allows function syntax, alt - can get messy when static functions needed
  • 14. components - code import React from 'react'; const Hello = ({name}) => { return ( <div> Hello, <b class='test-name'>{name}</b> </div> ); }; export default Hello;
  • 15. components - tests describe('hello component', () => { it('renders name', () => { const output = renderHello('Steve'); const name = getChildrenByClass(output, 'test-name'); expect(name.props.children).toEqual('Steve'); }); it('renders component', () => { const output = renderHello('Steve'); const expected = <div>Hello, <b class="test-name">Steve</b></div>; expect(output).toEqualJSX(expected); }); }); const renderHello = name => { const renderer = TestUtils.createRenderer(); renderer.render(<Hello name={name}/>); return renderer.getRenderOutput(); }
  • 16. components - tests describe('<MyComponent />', () => { it('renders three <Foo /> components', () => { const wrapper = shallow(<MyComponent />); expect(wrapper.find(Foo)).to.have.length(3); }); it('renders an `.icon-star`', () => { const wrapper = shallow(<MyComponent />); expect(wrapper.find('.icon-star')).to.have.length(1); }); it('renders children when passed in', () => { const wrapper = shallow( <MyComponent> <div className="unique" /> </MyComponent> ); expect(wrapper.contains(<div className="unique" />)).to.equal(true); }); it('simulates click events', () => { const onButtonClick = sinon.spy(); const wrapper = shallow( <Foo onButtonClick={onButtonClick} /> ); wrapper.find('button').simulate('click'); expect(onButtonClick.calledOnce).to.equal(true); }); }); airbnb/enzyme react element css class html element simulate event
  • 17. stores • redux - one, alt - many • redux - registers reducers, alt - defines logic to execute based on data passed by action • redux - no tests needed, test reducers, alt - the meat of logic, harder to test without side effects • redux - immutable, alt - mutable • alt - ReferenceError: A store named NamesStore already exists, double check your store names or pass in your own custom identifier for each store]
  • 18. stores - code import alt from '../alt'; import namesActions from '../actions/NamesActions'; class NamesStore { constructor() { this.bindListeners({ add: namesActions.ADD}) this.state = { names: [] } } add(name) { if (name === 'Stranger') { return this.state; } this.setState({ names: [...this.state.names, name] }); } } export default function configureStore() { return alt.createStore(NamesStore, 'NamesStore'); }
  • 19. stores - tests import alt from '../alt'; import configureStore from './configureNamesStore'; import namesActions from '../actions/NamesActions'; const greet = name => { const action = namesActions.ADD; const data = name; alt.dispatcher.dispatch({ action, data }); }; describe('store', () => { it('starts off with empty names array', () => { const store = configureStore(); const state = store.getState(); expect(state).toEqual({ names: []}); }); it('adds a name after greet action processed', () => { const store = configureStore(); greet('Steve'); const state = store.getState(); expect(state).toEqual({ names: ['Steve']}); }); });
  • 20. reducers • pure functions - zero side-effects, only rely on parameter values • super easy to test • they scale - easy to add a new one
  • 21. reducers - code const shouldGreet = name => { return name !== 'Stranger'; }; const namesReducer = (state = { names: [] }, action) => { if (action.type === 'GREET' && shouldGreet(action.payload.name)) { return { names: [...state.names, action.payload.name] }; } return state; }; export default namesReducer;
  • 22. reducers - tests import expect from 'expect'; import namesReducer from './namesReducer'; const greet = name => { return { type: 'GREET', payload: { name: name }}; }; describe('names reducer', () => { it('greets', () => { const state = namesReducer({ names: [] }, greet('Steve')); expect(state).toEqual({ names: ['Steve']}); }); it('no greetings to Stranger', () => { const state = namesReducer({ names: [] }, greet('Stranger')); expect(state).toEqual({ names: []}); }); });
  • 23. react-redux glue const store = configureStore(); render( <Provider store={store}> <App /> </Provider>, document.getElementById('App') ) 1
  • 24. react-redux glue import React from 'react'; import {connect} from 'react-redux'; import Hello from './hello'; const HelloList = ({ names }) => { return (<div className='test-hello-name-list'> {names.map(name => <Hello name={name}/> )} </div>); } const mapStateToProps = state => { return { names: state.names } } export default connect(mapStateToProps)(HelloList); 2
  • 25. react-alt glue // Bad: getting into lib internals import connectToStores from 'alt-utils/lib/connectToStores'; class HelloList extends React.Component { static getStores(props) { return [store]; } static getPropsFromStores(props) { return store.getState(); } render() { return ( <div className='test-hello-name-list'> {this.props.names.map(name => <Hello name={name}/> ) } </div> ); } } export default connectToStores(HelloList); 1
  • 26. react-alt glueclass Greet extends React.Component { constructor(props) { super(props); this.submit = this.submit.bind(this); } static getStores(props) { return [store] } static getPropsFromStores(props) { return store.getState(); } submit(e) { e.preventDefault(); namesActions.add(this.input.value); } render() { return ( <div className='test-greet'> <form onSubmit={this.submit}> <input id='test-greeting' type='text' ref={node => { this.input = node}}/> <button id='test-submit-greeting' type='submit'>Greet</button> </form> </div> ); } }; export default connectToStores(Greet); 1
  • 27. application stats 35 ./hello-alt/components/greet.jsx 11 ./hello-alt/components/hello.jsx 32 ./hello-alt/components/hello.test.js 25 ./hello-alt/components/helloList.jsx 20 ./hello-alt/state/configureNamesStore.js 24 ./hello-alt/state/configureNamesStore.test.js 2 ./hello-alt/state/namesStore.js 8 ./hello-alt/actions/NamesActions.js 4 ./hello-alt/alt.js 12 ./hello-alt/index.js 21 ./hello-redux/components/greet.jsx 11 ./hello-redux/components/hello.jsx 32 ./hello-redux/components/hello.test.js 12 ./hello-redux/components/helloList.jsx 6 ./hello-redux/state/store.js 12 ./hello-redux/state/namesReducer.js 17 ./hello-redux/state/namesReducer.test.js 19 ./hello-redux/app.jsx 14 ./hello-redux/index.js lines of code 144 total 173 total = 20 % more
  • 29. stats redux alt version 3.5.2 0.18.4 size 5.9K (2kb?) 23K downloads / month 670K 38K repo reactjs/redux goatslacker/alt open issues 44 79 pull requests 20 4 last commit hours ago almost a month ago
  • 30. comparison redux alt Open Systems Don't Always Win - Steve Jobs
  • 31. verdict TRIAL Redux is a great, mature tool that has helped many of our teams reframe how they think about managing state in client-side apps. Using a Flux-style approach, it enables a loosely coupled state-machine architecture that's easy to reason about. We've found it a good companion to some of our favored JavaScript frameworks, such as Ember and React - ThoughtWorks TechRadar 2016 April HOLD Alt although says to be unopinionated it pushes to use action objects, static functions that are used to connect components to stores, possible to mutate store state and having multiple stores might encourage a monolith approach, doesn’t have as big community backing as Redux and feels dated in comparison
  • 32. end to end tests var process = require('process'); var port = process.env.PORT; function navigateToSite(test) { return test.open('http://localhost:' + port); } module.exports = { 'says hello': function (test) { navigateToSite(test) .assert.doesntExist('.test-name', 'initial state has no greetings') .type('#test-greeting', 'Steve') .click('#test-submit-greeting') .assert.text('.test-hello', 'Hello, Steve', 'adds a new greeting') .done(); } }; give confidence when switching frameworks *don’t use dalekjs
  • 33. example site - TES Global
  • 35. one way to implement implementation by TES Global
  • 36. – Antoine de Saint Exupéry It seems that perfection is attained, not when there is nothing more to add, but when there is nothing more to take away q&a
  • 37. links • http://redux.js.org • http://alt.js.org • https://github.com/airbnb/enzyme • https://egghead.io/series/react-testing-cookbook • https://egghead.io/series/getting-started-with-redux • http://redux.js.org/docs/recipes/WritingTests.html • https://github.com/gaearon/redux-devtools • https://github.com/uldissturms/talks