futurice/redux-training

Name: redux-training

Owner: Futurice

Description: null

Created: 2016-10-26 12:45:45.0

Updated: 2017-07-23 23:46:38.0

Pushed: 2016-10-26 12:55:22.0

Homepage: null

Size: 12

Language: JavaScript

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

Redux

Arkkitehtuurikirjasto JavaScript-applikaatioille

Esimerkkiprojektin alkuun:

clone git@github.com:futurice/redux-training.git
edux-training
checkout tags/1
install
start
1. Termit
Tila

Kaikki sovelluksen sisällä oleva tieto. Määrittää esimerkiksi sen, mitä käyttäjä näkee tietyllä ajan hetkellä. Esimerkiksi valokatkaisijan tila voi olla joko päällä tai pois päältä.

Pelin tila:


meRunning: true,
ints: 120,
ayer: {
health: 20,
position: {
  x: 245,
  y: 0
}


Websovelluksen tila:


ggedIn: true,
er: {
username: 'rikurouvila'
firstname: 'Riku'

rrentView: 'feed',
sibleTweets: [...]

Action

Sovelluksessa tapahtunut tapahtuma, esimerkiksi painikkeen painallus, uusi viesti, näkymän vaihtuminen


pe: 'USER_LOGGED_IN',
yload: {
username: 'rikurouvila',
profilePic: '...'


Reduxissa action mallinnetaan tyypillisesti objektina, jolla on kentät type ja payload

Reducer

Funktio joka saa parametreikseen edellisen tilan ja juuri tapahtuneen tapahtuman ja palauttaa päivitetyn tilan

tion myReducer(previousState, action) {
(action.type === 'USER_LOGGED_IN') {
const newState = {
  user: action.payload
};
return newState;


Synkronisuus / Asynkronisuus

Esimerkiksi synkroninen funktio palauttaa tuloksen heti sen jälkeen kun sitä kutsutaan

t sum = sumNumbers(1,2); // 3

Asynkroninen kutsu palauttaa tuloksen vasta määrittelemättömän ajan jälkeen. Asynkronisen funktion tunnistaa usein siitä, että sille syötetty viimeinen parametri on “callback” funktio, jota kutsutaan kun toiminto valmistuu.

ser('rikurouvila', function(error, user) {
nsole.log(user);

Tälläiset funktiot voivat palauttaa myös promise-objektin, mutta perusidea on sama.

ser('rikurouvila').then(function(user) {
nsole.log(user);

2. React komponentin oma tila

t App = React.createClass({
tInitialState() {
return {
  clicks: 0
};

Click() {
this.setState({
  clicks: this.state.clicks + 1
});

nder() {
return (
  <div>
    <h1>Click counter</h1>
    <p>Button clicked {this.state.clicks} times</p>
    <button onClick={this.onClick}>Click here</button>
  </div>
)


Kun kyseessä on komponentin oma tila (ei sovelluksen tila)

Esimerkkejä komponentin tilasta:

Esimerkkejä sovelluksen tilasta:

Valmis Click counter komponentti: git checkout tags/2

3. Sovelluksen tilan toteutus Reduxilla

Valmis Click counter komponentti, jonka tila tallennetaan sovelluksen (reduxin) tilaan:

git checkout tags/3

4. Hakusovellus

Pohja: git checkout tags/4

Sovelluslogiikan paloittelu

Sovelluslogiikka kannattaa pyrkiä erottamaan mahdollisimman pitkälle React-komponenteista ja Reduxin reducereista.

Esimerkiksi tässä sovelluksessa itse haun toteuttava toiminnallisuus voidaan toteuttaa omaan search.js moduuliinsa

ervices/search.js
rt function searchWithTerm(term) {
 tekee haun annetulla termillä ja palauttaa tuloksen

Redux-logiikan paloittelu

Sillä oikeassa sovelluksessa reducereita ja actioneita voi olla kymmeniä, kannattaa myös yhtä sovelluksen konseptia vastaava logiikka erottaa omaan tiedostoonsa

ucks/search.js

rt { searchWithTerm } from '../services/search';

rt function searchAction(searchTerm) {
turn function(dispatch, getState) {
// tee haku, lähetä uusi action kun se valmistuu



rt default function reducer(state, action) {
 tilanhallinta

Konsepteittain jaoiteltu projekti: git checkout tags/5

5. Asynkroniset tapahtumat ja redux-thunk
Middlewaret

Mahdollistavat custom-toiminnallisuuden toteuttamisen storelle

t store = createStore(reducer, applyMiddleware(thunk));
redux-thunk

Valmis middleware reduxille. Mahdollistaa funktioiden käytön actioneina.

{type: __, payload: __} vs

tion(dispatch, getState) {


redux-thunk kutsuu funktiota kahdella parametrillä

Näiden avulla action-funktio voi nyt käytännössä lähettää uusia actioneita ihan milloin tahansa esim. 1 sekunnin päästä tai kun kysely rajapintaan valmistuu.

t actionAfter1000ms = function(dispatch, getState) {
tTimeout(function() {
dispatch({type: 'HELLO', payload: 'WORLD'});
 1000)


.props.dispatch(actionAfter1000ms);

Haku toteutettuna redux-thunkilla: git checkout tags/6

6. Asynkroniset tapahtumat ja redux-loop
rt { install } from 'redux-loop';
t store = createStore(reducer, install());

Redux-loop vie sivuvaikutusten luomisen

rt { loop, Effects } from 'redux-loop';

rt default function reducer(state = INITIAL_STATE, action = {}) {
itch(action.type) {
case SEARCH:
  return loop(state, Effects.promise(searchEffect, action.payload));

Haku toteutettuna redux-loopilla: git checkout tags/7

Liitteet

Nimitietokannan nimet

t DATABASE = [
amela',
arcus',
rystina',
irella',
amantha',
ena',
iu',
lden',
shely',
abel',
ibrada',
ulda',
liza',
helley',
eroy',
eriberto',
anita',
esica',
ndia',
en'

Redux

http://redux.js.org/

React-redux

https://github.com/reactjs/react-redux

Ducks

https://github.com/erikras/ducks-modular-redux

Redux Thunk dokumentaatio

https://github.com/gaearon/redux-thunk

Redux Loop 2.2 dokumentaatio

https://github.com/redux-loop/redux-loop/tree/0da84e946e2b262f98c836ad310fcd0d80bee94d


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.