SlideShare ist ein Scribd-Unternehmen logo
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

PDF
Storytelling For The Web: Integrate Storytelling in your Design Process
PDF
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
PDF
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
PDF
2024 Trend Updates: What Really Works In SEO & Content Marketing
PDF
React & Redux
PDF
EventStorming für Domain-Driven Design
PDF
Specification by Example
PDF
2024 State of Marketing Report – by Hubspot
Storytelling For The Web: Integrate Storytelling in your Design Process
Artificial Intelligence, Data and Competition – SCHREPEL – June 2024 OECD dis...
How to Leverage AI to Boost Employee Wellness - Lydia Di Francesco - SocialHR...
2024 Trend Updates: What Really Works In SEO & Content Marketing
React & Redux
EventStorming für Domain-Driven Design
Specification by Example
2024 State of Marketing Report – by Hubspot
Anzeige

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