SlideShare ist ein Scribd-Unternehmen logo
1 von 74
Downloaden Sie, um offline zu lesen
Einführung in React.js und Redux
Warum React.js?
React.js
Eine JavaScript Library zum Erstellen von User Interfaces
Nur die UI
Virtual DOM
Data Flow
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 3
Data Flow
Unidirektional ohne Event-Chaos
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 4
http://www.wikihow.com/Image:Make-Spaghetti-Step-1.jpg
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 5
http://www.wikihow.com/Image:Make-Spaghetti-Step-1.jpg
https://www.flickr.com/photos/spilt-milk/5829575950
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 6
Entwicklungsgeschichte einer Pub-Sub-Software
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 7
Entwicklungsgeschichte einer Pub-Sub-Software
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 8
Entwicklungsgeschichte einer Pub-Sub-Software
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 9
React Data Flow
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 10
Virtual DOM
Effizientes UI-Rendering inklusive
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 11
Änderungen auf der UI - was tun?
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 12
Änderungen auf der UI - was tun?
Alles neuzeichnen? Flackert!
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 13
Änderungen auf der UI - was tun?
Alles neuzeichnen? Flackert!
DOM manipulieren? Mühsam!
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 14
Virtual DOM
Entwickler beschreibt das vollständige Resultat
React aktualisiert den DOM mit minimalen Änderungen
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 15
Nur die UI
Model ist kein Bestandteil von React
Kann beliebig implementiert werden
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 16
Einführung in React.js
Eine einfache Komponente
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in React.js – Folie 18
Der Code als Class Component
import React, { Component } from "react";
export default class extends Component {
render() {
return <p>Hello World!</p>;
}
}
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in React.js – Folie 19
Der Code als Class Component ohne JSX
import React, { Component } from "react";
export default class extends Component {
render() {
return React.createElement(’p’, null, ’Hello World!’);
}
}
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in React.js – Folie 20
Der Code als Stateless Functional Component
import React from "react";
export default () => <p>Hello World!</p>;
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in React.js – Folie 21
Der Code als Stateless Functional Component
import React from "react";
export default () => <p>Hello World!</p>;
Verwendung:
import HelloWorld from "./myFile";
<HelloWorld />
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in React.js – Folie 22
React.js Testen mit Shallow Rendering
Shallow Rendering - Was ist das?
Seit React 0.13 (März 2015)
Erlaubt das Testen von Komponenten ohne DOM
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React.js Testen mit Shallow Rendering – Folie 24
Essentielle Testing Library
Enzyme
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React.js Testen mit Shallow Rendering – Folie 25
Essentielle Testing Library
Enzyme
Shallow Rendering
Full DOM Rendering
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React.js Testen mit Shallow Rendering – Folie 26
Shallow Rendering
Shallow rendering ist hilfreich, um
Tests auf eine Komponente zu beschränken
sicherzustellen, dass die Tests nicht vom Verhalten von
Kind-Komponenten abhängen
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React.js Testen mit Shallow Rendering – Folie 27
Ein Shallow Rendering Test
const component = shallow(<HelloWorld />);
expect(component.text()).to.be("Hello World!");
expect(component.type()).to.be("p");
expect(component.name()).to.be("p");
expect(component.html()).to.be("<p>Hello World!</p>");
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React.js Testen mit Shallow Rendering – Folie 28
React Developer Tools
Demo
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React Developer Tools – Folie 30
Erstellen einer Benutzerverwaltung
Anzeige eines Benutzers
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 32
Datenübergabe
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 33
Datenübergabe
<MyComponent aProperty={myData} anotherProperty={moreData} />
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 34
Datenübergabe
<MyComponent aProperty={myData} anotherProperty={moreData} />
class MyComponent extends Component {
/* ... */ this.props.aProperty /* ... */
/* ... */ this.props.anotherProperty /* ... */
}
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 35
Datenübergabe
<MyComponent aProperty={myData} anotherProperty={moreData} />
class MyComponent extends Component {
/* ... */ this.props.aProperty /* ... */
/* ... */ this.props.anotherProperty /* ... */
}
export default props =>
/* ... */ props.aProperty /* ... */
/* ... */ props.anotherProperty /* ... */
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 36
Datenübergabe
<MyComponent aProperty={myData} anotherProperty={moreData} />
class MyComponent extends Component {
/* ... */ this.props.aProperty /* ... */
/* ... */ this.props.anotherProperty /* ... */
}
export default props =>
/* ... */ props.aProperty /* ... */
/* ... */ props.anotherProperty /* ... */
export default ({aProperty, anotherProperty}) =>
/* ... */ aProperty /* ... */
/* ... */ anotherProperty /* ... */
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 37
Die Implementierung der User-Komponente
import React from "react";
export default ({firstName, lastName}) => (
<div>
<label>First name: </label><span>{firstName}</span><br/>
<label>Last name: </label><span>{lastName}</span><br/>
</div>
);
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 38
Die Implementierung der User-Komponente
import React from "react";
export default ({firstName, lastName}) => (
<div>
<label>First name: </label><span>{firstName}</span><br/>
<label>Last name: </label><span>{lastName}</span><br/>
</div>
);
<User firstName="Petra" lastName="Meier" />
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 39
Testen der Datenübergabe
const user =
shallow(<User firstName="Petra" lastName="Meier" />);
const nameParts = user.find("span");
expect(nameParts.length).to.be(2);
expect(nameParts.at(0).text()).to.be("Petra");
expect(nameParts.at(1).text()).to.be("Meier");
expect(nameParts.map(c => c.text()))
.to.eql(["Petra", "Meier"]);
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 40
Anzeige einer Liste von Benutzern
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 41
Die Implementierung der UserList-Komponente
import React from "react";
import User from "./User";
export default ({users}) => (
<ul>
{ users.map( user =>
<li key={"userlist_" + user.firstName + user.lastName}>
<User {...user} />
</li> ) }
</ul>
);
Wichtig: Der Key sollte eine semantische Beziehung zur Komponente
haben.
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 42
Was sollte hier getestet werden?
<ul>
{ users.map( user =>
<li key={"userlist_" + user.firstName + user.lastName}>
<User {...user} />
</li> ) }
</ul>
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 43
Was sollte hier getestet werden?
<ul>
{ users.map( user =>
<li key={"userlist_" + user.firstName + user.lastName}>
<User {...user} />
</li> ) }
</ul>
Die Listeneinträge
Die Aufrufe der User-Komponente
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 44
Testen der li Elemente
const users = shallow(<UserList users={[
{firstName:"Petra", lastName:"Meier"},
{firstName:"Peter", lastName:"Miller"}]} />);
const elems = users.find("li");
expect(elems.length).to.be(2);
expect(elems.at(0).key()).to.be("userlist_PetraMeier");
expect(elems.at(1).key()).to.be("userlist_PeterMiller");
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 45
Testen der Aufrufe der User-Komponente
const userComps = users.find(User);
expect(userComps.length).to.be(2);
expect(userComps.at(0).key()).to.be.null();
expect(userComps.at(0).props())
.to.eql({firstName:"Petra", lastName:"Meier"});
expect(userComps.at(1).props())
.to.eql({firstName:"Peter", lastName:"Miller"});
expect(userComps.at(0).prop("firstName")).to.eql("Petra");
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 46
Anlegen eines Benutzers
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 47
Verwenden der eingegebenen Daten
<div>
<label>First name:</label>
<input type="text"
onBlur={e => this.setState({firstName: e.target.value})} />
</div>
<div>
<button
onClick={() => { this.props.submitUser(this.state); }}
>Submit</button>
</div>
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 48
Testen der User-Erzeugung
Shallow rendern der Komponente mit einem Spy als Callback:
import sinon from "sinon";
beforeEach(function () {
this.submit = sinon.spy();
this.user = shallow(<UserCreation submitUser={this.submit
}/>);
});
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 49
(Blackbox) Testen des Callback-Aufrufs
it("blackbox test", function () {
const inputs = this.user.find("input");
inputs.at(0).simulate("blur", {target:{value: "Nicole"}});
inputs.at(1).simulate("blur", {target:{value: "Rauch"}});
const button = this.user.find("button"); // .first();
button.simulate("click");
expect(this.submit.getCall(0).args)
.to.eql([{firstName: "Nicole", lastName: "Rauch"}]);
});
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 50
Einführung in Redux
React Data Flow
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 52
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 53
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 54
Redux Data Flow
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 55
Action
const USER_ADDED = "USER_ADDED";
function addUser(user) {
return {
type: USER_ADDED,
payload: user
}
}
Sehr ähnlich zu CQRS / Event Sourcing
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 56
State Tree
INITIAL_STATE = {
users: []
};
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 57
Reducers
function reducers(state = INITIAL_STATE, action = {}) {
return {
users: users(state.users, action)
};
}
function users(state, action) {
switch (action.type) {
case USER_ADDED:
return state.concat(action.payload);
}
return state;
}
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 58
Integration in die Komponente
<div>
<div>User Creation</div>
<div><label>First name:</label> <input type="text"/></div>
<div><label>Last name:</label> <input type="text"/></div>
<div>
<button onClick={
/* ... */
}>Submit</button>
</div>
</div>
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 59
Integration in die Komponente
<div>
<div>User Creation</div>
<div><label>First name:</label> <input type="text"/></div>
<div><label>Last name:</label> <input type="text"/></div>
<div>
<button onClick={
() => {this.props.submitUser(
{firstName: ..., lastName: ...}
)}
}>Submit</button>
</div>
</div>
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 60
Der Callback
<UserCreation submitUser={
user => this.props.dispatch(Actions.addUser(user))
}/>
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 61
Redux Tools
Redux Logger Demo
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Redux Tools – Folie 63
Redux Developer Tools Demo
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Redux Tools – Folie 64
Asynchrone Calls
Redux Middleware für asynchrone Calls
Möglichkeiten zum Behandeln asynchroner Calls:
redux-thunk
redux-promise
rxjs mit redux-observable
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 66
Asynchroner Dispatch
export function asyncActionInANutshell() {
return (dispatch, getState) => {
const { someStatePart } = getState();
dispatch(readyToTakeOff());
performBackendCall(params, response => {
dispatch(anActionFor(response));
});
};
}
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 67
Verwendung in userer Applikation
Benutzerdaten ans Backend schicken zum Persistieren
Alle Benutzer vom Backend laden
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 68
Benutzerdaten ans Backend schicken
Vorher:
this.props.dispatch(addUser(user))
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 69
Benutzerdaten ans Backend schicken
Vorher:
this.props.dispatch(addUser(user))
Jetzt:
export function submitUser(user) {
return dispatch => {
backend.postUser(user, returnCode => {
if(returnCode === 200) {
dispatch(addUser(user));
}
});
};
}
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 70
Benutzerdaten ans Backend schicken
export function postUser(user, callback) {
ajax.ajax({
url: "/api/user",
method: "POST",
body: "firstName=" + user.firstName + "&lastName=" +
user.lastName
},
(code) => {
callback(code);
}
);
}
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 71
Integration in die Applikation
<UserCreation submitUser={
user => { this.props.dispatch(submitUser(user)); }
} />
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 72
Credits
Motivation: Hamza Butt – Workout, Gym, Squats
http://costculator.com/best-rowing-machine-reviews/
React.js:
http://www.goodworklabs.com/wp-content/uploads/2016/10/reactjs.png
React Shallow Rendering: anokarina – Does dipping my toes into the
Sound count as touching the Pacific Ocean?
https://www.flickr.com/photos/anokarina/20044358984
User Management: James Cridland – Crowd
https://www.flickr.com/photos/jamescridland/613445810/
React / Redux Tools: C_osett – Google Developer Tools
https://www.flickr.com/photos/mstable/17517988852/
Async Calls: David Williss – The Smoke Signal
https://www.flickr.com/photos/dwilliss/7730219512
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Abspann – Folie 73
Vielen Dank!
Nicole Rauch
E-Mail info@nicole-rauch.de
Twitter @NicoleRauch
Web http://www.nicole-rauch.de
Code https://github.com/NicoleRauch/RR3Code
React.js Ein- und mehrtägige Workshops / Consulting / Entwicklung
© 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Abspann – Folie 74

Weitere ähnliche Inhalte

Ähnlich wie Einführung in React.js und Redux (Web Developer Conference 2017)

OpenSocial und Apache Shindig
OpenSocial und Apache ShindigOpenSocial und Apache Shindig
OpenSocial und Apache ShindigMayflower GmbH
 
W-Jax 2015: QS-Maßnahmen bei Continuous Delivery
W-Jax 2015: QS-Maßnahmen bei Continuous DeliveryW-Jax 2015: QS-Maßnahmen bei Continuous Delivery
W-Jax 2015: QS-Maßnahmen bei Continuous DeliveryStephan Kaps
 
Einführung in ASP.NET Core Middlewares
Einführung in ASP.NET Core MiddlewaresEinführung in ASP.NET Core Middlewares
Einführung in ASP.NET Core MiddlewaresMatthias Jauernig
 
CodeTalks Vortrag: Automatisierung mit Ansible & Jenkins @ LeanIX Enterprise ...
CodeTalks Vortrag: Automatisierung mit Ansible & Jenkins @ LeanIX Enterprise ...CodeTalks Vortrag: Automatisierung mit Ansible & Jenkins @ LeanIX Enterprise ...
CodeTalks Vortrag: Automatisierung mit Ansible & Jenkins @ LeanIX Enterprise ...LeanIX GmbH
 
Ionic 2 - Hybridapps auf Steroiden
Ionic 2 - Hybridapps auf SteroidenIonic 2 - Hybridapps auf Steroiden
Ionic 2 - Hybridapps auf SteroidenHendrik Lösch
 
Magdeburger Developer Days 2018 - Warum warten auf die IDE?
Magdeburger Developer Days 2018 - Warum warten auf die IDE?Magdeburger Developer Days 2018 - Warum warten auf die IDE?
Magdeburger Developer Days 2018 - Warum warten auf die IDE?Robin Sedlaczek
 
HTML5 und node.js Grundlagen
HTML5 und node.js GrundlagenHTML5 und node.js Grundlagen
HTML5 und node.js GrundlagenMayflower GmbH
 
Von 0 auf 100 - Performance im Web
Von 0 auf 100 - Performance im WebVon 0 auf 100 - Performance im Web
Von 0 auf 100 - Performance im WebSebastian Springer
 
Vortrag HTML5, CSS3, PhoneGap
Vortrag  HTML5, CSS3, PhoneGapVortrag  HTML5, CSS3, PhoneGap
Vortrag HTML5, CSS3, PhoneGaprene_peinl
 
2012-10-12 Testen mit Arquillian
2012-10-12 Testen mit Arquillian2012-10-12 Testen mit Arquillian
2012-10-12 Testen mit ArquillianMatthias Reining
 
Vorstellung Open Social Ipc 2009
Vorstellung Open Social Ipc 2009Vorstellung Open Social Ipc 2009
Vorstellung Open Social Ipc 2009fruske
 

Ähnlich wie Einführung in React.js und Redux (Web Developer Conference 2017) (20)

OpenSocial und Apache Shindig
OpenSocial und Apache ShindigOpenSocial und Apache Shindig
OpenSocial und Apache Shindig
 
W-Jax 2015: QS-Maßnahmen bei Continuous Delivery
W-Jax 2015: QS-Maßnahmen bei Continuous DeliveryW-Jax 2015: QS-Maßnahmen bei Continuous Delivery
W-Jax 2015: QS-Maßnahmen bei Continuous Delivery
 
Einführung in React
Einführung in ReactEinführung in React
Einführung in React
 
TypeScript
TypeScriptTypeScript
TypeScript
 
Codeception VisualCeption
Codeception VisualCeptionCodeception VisualCeption
Codeception VisualCeption
 
Einführung in ASP.NET Core Middlewares
Einführung in ASP.NET Core MiddlewaresEinführung in ASP.NET Core Middlewares
Einführung in ASP.NET Core Middlewares
 
Enterprise APEX
Enterprise APEXEnterprise APEX
Enterprise APEX
 
CodeTalks Vortrag: Automatisierung mit Ansible & Jenkins @ LeanIX Enterprise ...
CodeTalks Vortrag: Automatisierung mit Ansible & Jenkins @ LeanIX Enterprise ...CodeTalks Vortrag: Automatisierung mit Ansible & Jenkins @ LeanIX Enterprise ...
CodeTalks Vortrag: Automatisierung mit Ansible & Jenkins @ LeanIX Enterprise ...
 
Ionic 2 - Hybridapps auf Steroiden
Ionic 2 - Hybridapps auf SteroidenIonic 2 - Hybridapps auf Steroiden
Ionic 2 - Hybridapps auf Steroiden
 
Magdeburger Developer Days 2018 - Warum warten auf die IDE?
Magdeburger Developer Days 2018 - Warum warten auf die IDE?Magdeburger Developer Days 2018 - Warum warten auf die IDE?
Magdeburger Developer Days 2018 - Warum warten auf die IDE?
 
HTML5 und node.js Grundlagen
HTML5 und node.js GrundlagenHTML5 und node.js Grundlagen
HTML5 und node.js Grundlagen
 
Was ist neu in .NET 4.5?
Was ist neu in .NET 4.5?Was ist neu in .NET 4.5?
Was ist neu in .NET 4.5?
 
Von 0 auf 100 - Performance im Web
Von 0 auf 100 - Performance im WebVon 0 auf 100 - Performance im Web
Von 0 auf 100 - Performance im Web
 
Vortrag HTML5, CSS3, PhoneGap
Vortrag  HTML5, CSS3, PhoneGapVortrag  HTML5, CSS3, PhoneGap
Vortrag HTML5, CSS3, PhoneGap
 
TDD für Testmuffel
TDD für TestmuffelTDD für Testmuffel
TDD für Testmuffel
 
Automatisierung mit grunt
Automatisierung mit gruntAutomatisierung mit grunt
Automatisierung mit grunt
 
Windows 8.1 UI für Entwickler
Windows 8.1 UI für EntwicklerWindows 8.1 UI für Entwickler
Windows 8.1 UI für Entwickler
 
2012-10-12 Testen mit Arquillian
2012-10-12 Testen mit Arquillian2012-10-12 Testen mit Arquillian
2012-10-12 Testen mit Arquillian
 
Vorstellung Open Social Ipc 2009
Vorstellung Open Social Ipc 2009Vorstellung Open Social Ipc 2009
Vorstellung Open Social Ipc 2009
 
Workshop Vue js
Workshop Vue jsWorkshop Vue js
Workshop Vue js
 

Einführung in React.js und Redux (Web Developer Conference 2017)

  • 3. React.js Eine JavaScript Library zum Erstellen von User Interfaces Nur die UI Virtual DOM Data Flow © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 3
  • 4. Data Flow Unidirektional ohne Event-Chaos © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 4
  • 5. http://www.wikihow.com/Image:Make-Spaghetti-Step-1.jpg © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 5
  • 7. Entwicklungsgeschichte einer Pub-Sub-Software © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 7
  • 8. Entwicklungsgeschichte einer Pub-Sub-Software © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 8
  • 9. Entwicklungsgeschichte einer Pub-Sub-Software © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 9
  • 10. React Data Flow © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 10
  • 11. Virtual DOM Effizientes UI-Rendering inklusive © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 11
  • 12. Änderungen auf der UI - was tun? © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 12
  • 13. Änderungen auf der UI - was tun? Alles neuzeichnen? Flackert! © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 13
  • 14. Änderungen auf der UI - was tun? Alles neuzeichnen? Flackert! DOM manipulieren? Mühsam! © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 14
  • 15. Virtual DOM Entwickler beschreibt das vollständige Resultat React aktualisiert den DOM mit minimalen Änderungen © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 15
  • 16. Nur die UI Model ist kein Bestandteil von React Kann beliebig implementiert werden © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Warum React.js? – Folie 16
  • 18. Eine einfache Komponente © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in React.js – Folie 18
  • 19. Der Code als Class Component import React, { Component } from "react"; export default class extends Component { render() { return <p>Hello World!</p>; } } © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in React.js – Folie 19
  • 20. Der Code als Class Component ohne JSX import React, { Component } from "react"; export default class extends Component { render() { return React.createElement(’p’, null, ’Hello World!’); } } © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in React.js – Folie 20
  • 21. Der Code als Stateless Functional Component import React from "react"; export default () => <p>Hello World!</p>; © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in React.js – Folie 21
  • 22. Der Code als Stateless Functional Component import React from "react"; export default () => <p>Hello World!</p>; Verwendung: import HelloWorld from "./myFile"; <HelloWorld /> © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in React.js – Folie 22
  • 23. React.js Testen mit Shallow Rendering
  • 24. Shallow Rendering - Was ist das? Seit React 0.13 (März 2015) Erlaubt das Testen von Komponenten ohne DOM © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React.js Testen mit Shallow Rendering – Folie 24
  • 25. Essentielle Testing Library Enzyme © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React.js Testen mit Shallow Rendering – Folie 25
  • 26. Essentielle Testing Library Enzyme Shallow Rendering Full DOM Rendering © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React.js Testen mit Shallow Rendering – Folie 26
  • 27. Shallow Rendering Shallow rendering ist hilfreich, um Tests auf eine Komponente zu beschränken sicherzustellen, dass die Tests nicht vom Verhalten von Kind-Komponenten abhängen © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React.js Testen mit Shallow Rendering – Folie 27
  • 28. Ein Shallow Rendering Test const component = shallow(<HelloWorld />); expect(component.text()).to.be("Hello World!"); expect(component.type()).to.be("p"); expect(component.name()).to.be("p"); expect(component.html()).to.be("<p>Hello World!</p>"); © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React.js Testen mit Shallow Rendering – Folie 28
  • 30. Demo © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. React Developer Tools – Folie 30
  • 32. Anzeige eines Benutzers © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 32
  • 33. Datenübergabe © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 33
  • 34. Datenübergabe <MyComponent aProperty={myData} anotherProperty={moreData} /> © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 34
  • 35. Datenübergabe <MyComponent aProperty={myData} anotherProperty={moreData} /> class MyComponent extends Component { /* ... */ this.props.aProperty /* ... */ /* ... */ this.props.anotherProperty /* ... */ } © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 35
  • 36. Datenübergabe <MyComponent aProperty={myData} anotherProperty={moreData} /> class MyComponent extends Component { /* ... */ this.props.aProperty /* ... */ /* ... */ this.props.anotherProperty /* ... */ } export default props => /* ... */ props.aProperty /* ... */ /* ... */ props.anotherProperty /* ... */ © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 36
  • 37. Datenübergabe <MyComponent aProperty={myData} anotherProperty={moreData} /> class MyComponent extends Component { /* ... */ this.props.aProperty /* ... */ /* ... */ this.props.anotherProperty /* ... */ } export default props => /* ... */ props.aProperty /* ... */ /* ... */ props.anotherProperty /* ... */ export default ({aProperty, anotherProperty}) => /* ... */ aProperty /* ... */ /* ... */ anotherProperty /* ... */ © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 37
  • 38. Die Implementierung der User-Komponente import React from "react"; export default ({firstName, lastName}) => ( <div> <label>First name: </label><span>{firstName}</span><br/> <label>Last name: </label><span>{lastName}</span><br/> </div> ); © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 38
  • 39. Die Implementierung der User-Komponente import React from "react"; export default ({firstName, lastName}) => ( <div> <label>First name: </label><span>{firstName}</span><br/> <label>Last name: </label><span>{lastName}</span><br/> </div> ); <User firstName="Petra" lastName="Meier" /> © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 39
  • 40. Testen der Datenübergabe const user = shallow(<User firstName="Petra" lastName="Meier" />); const nameParts = user.find("span"); expect(nameParts.length).to.be(2); expect(nameParts.at(0).text()).to.be("Petra"); expect(nameParts.at(1).text()).to.be("Meier"); expect(nameParts.map(c => c.text())) .to.eql(["Petra", "Meier"]); © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 40
  • 41. Anzeige einer Liste von Benutzern © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 41
  • 42. Die Implementierung der UserList-Komponente import React from "react"; import User from "./User"; export default ({users}) => ( <ul> { users.map( user => <li key={"userlist_" + user.firstName + user.lastName}> <User {...user} /> </li> ) } </ul> ); Wichtig: Der Key sollte eine semantische Beziehung zur Komponente haben. © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 42
  • 43. Was sollte hier getestet werden? <ul> { users.map( user => <li key={"userlist_" + user.firstName + user.lastName}> <User {...user} /> </li> ) } </ul> © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 43
  • 44. Was sollte hier getestet werden? <ul> { users.map( user => <li key={"userlist_" + user.firstName + user.lastName}> <User {...user} /> </li> ) } </ul> Die Listeneinträge Die Aufrufe der User-Komponente © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 44
  • 45. Testen der li Elemente const users = shallow(<UserList users={[ {firstName:"Petra", lastName:"Meier"}, {firstName:"Peter", lastName:"Miller"}]} />); const elems = users.find("li"); expect(elems.length).to.be(2); expect(elems.at(0).key()).to.be("userlist_PetraMeier"); expect(elems.at(1).key()).to.be("userlist_PeterMiller"); © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 45
  • 46. Testen der Aufrufe der User-Komponente const userComps = users.find(User); expect(userComps.length).to.be(2); expect(userComps.at(0).key()).to.be.null(); expect(userComps.at(0).props()) .to.eql({firstName:"Petra", lastName:"Meier"}); expect(userComps.at(1).props()) .to.eql({firstName:"Peter", lastName:"Miller"}); expect(userComps.at(0).prop("firstName")).to.eql("Petra"); © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 46
  • 47. Anlegen eines Benutzers © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 47
  • 48. Verwenden der eingegebenen Daten <div> <label>First name:</label> <input type="text" onBlur={e => this.setState({firstName: e.target.value})} /> </div> <div> <button onClick={() => { this.props.submitUser(this.state); }} >Submit</button> </div> © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 48
  • 49. Testen der User-Erzeugung Shallow rendern der Komponente mit einem Spy als Callback: import sinon from "sinon"; beforeEach(function () { this.submit = sinon.spy(); this.user = shallow(<UserCreation submitUser={this.submit }/>); }); © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 49
  • 50. (Blackbox) Testen des Callback-Aufrufs it("blackbox test", function () { const inputs = this.user.find("input"); inputs.at(0).simulate("blur", {target:{value: "Nicole"}}); inputs.at(1).simulate("blur", {target:{value: "Rauch"}}); const button = this.user.find("button"); // .first(); button.simulate("click"); expect(this.submit.getCall(0).args) .to.eql([{firstName: "Nicole", lastName: "Rauch"}]); }); © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Erstellen einer Benutzerverwaltung – Folie 50
  • 52. React Data Flow © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 52
  • 53. © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 53
  • 54. © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 54
  • 55. Redux Data Flow © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 55
  • 56. Action const USER_ADDED = "USER_ADDED"; function addUser(user) { return { type: USER_ADDED, payload: user } } Sehr ähnlich zu CQRS / Event Sourcing © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 56
  • 57. State Tree INITIAL_STATE = { users: [] }; © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 57
  • 58. Reducers function reducers(state = INITIAL_STATE, action = {}) { return { users: users(state.users, action) }; } function users(state, action) { switch (action.type) { case USER_ADDED: return state.concat(action.payload); } return state; } © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 58
  • 59. Integration in die Komponente <div> <div>User Creation</div> <div><label>First name:</label> <input type="text"/></div> <div><label>Last name:</label> <input type="text"/></div> <div> <button onClick={ /* ... */ }>Submit</button> </div> </div> © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 59
  • 60. Integration in die Komponente <div> <div>User Creation</div> <div><label>First name:</label> <input type="text"/></div> <div><label>Last name:</label> <input type="text"/></div> <div> <button onClick={ () => {this.props.submitUser( {firstName: ..., lastName: ...} )} }>Submit</button> </div> </div> © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 60
  • 61. Der Callback <UserCreation submitUser={ user => this.props.dispatch(Actions.addUser(user)) }/> © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Einführung in Redux – Folie 61
  • 63. Redux Logger Demo © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Redux Tools – Folie 63
  • 64. Redux Developer Tools Demo © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Redux Tools – Folie 64
  • 66. Redux Middleware für asynchrone Calls Möglichkeiten zum Behandeln asynchroner Calls: redux-thunk redux-promise rxjs mit redux-observable © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 66
  • 67. Asynchroner Dispatch export function asyncActionInANutshell() { return (dispatch, getState) => { const { someStatePart } = getState(); dispatch(readyToTakeOff()); performBackendCall(params, response => { dispatch(anActionFor(response)); }); }; } © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 67
  • 68. Verwendung in userer Applikation Benutzerdaten ans Backend schicken zum Persistieren Alle Benutzer vom Backend laden © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 68
  • 69. Benutzerdaten ans Backend schicken Vorher: this.props.dispatch(addUser(user)) © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 69
  • 70. Benutzerdaten ans Backend schicken Vorher: this.props.dispatch(addUser(user)) Jetzt: export function submitUser(user) { return dispatch => { backend.postUser(user, returnCode => { if(returnCode === 200) { dispatch(addUser(user)); } }); }; } © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 70
  • 71. Benutzerdaten ans Backend schicken export function postUser(user, callback) { ajax.ajax({ url: "/api/user", method: "POST", body: "firstName=" + user.firstName + "&lastName=" + user.lastName }, (code) => { callback(code); } ); } © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 71
  • 72. Integration in die Applikation <UserCreation submitUser={ user => { this.props.dispatch(submitUser(user)); } } /> © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Asynchrone Calls – Folie 72
  • 73. Credits Motivation: Hamza Butt – Workout, Gym, Squats http://costculator.com/best-rowing-machine-reviews/ React.js: http://www.goodworklabs.com/wp-content/uploads/2016/10/reactjs.png React Shallow Rendering: anokarina – Does dipping my toes into the Sound count as touching the Pacific Ocean? https://www.flickr.com/photos/anokarina/20044358984 User Management: James Cridland – Crowd https://www.flickr.com/photos/jamescridland/613445810/ React / Redux Tools: C_osett – Google Developer Tools https://www.flickr.com/photos/mstable/17517988852/ Async Calls: David Williss – The Smoke Signal https://www.flickr.com/photos/dwilliss/7730219512 © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Abspann – Folie 73
  • 74. Vielen Dank! Nicole Rauch E-Mail info@nicole-rauch.de Twitter @NicoleRauch Web http://www.nicole-rauch.de Code https://github.com/NicoleRauch/RR3Code React.js Ein- und mehrtägige Workshops / Consulting / Entwicklung © 2016 - 2017 Nicole Rauch. Alle Rechte vorbehalten. Abspann – Folie 74