PHP týden Předvánoční slevová akce
Pouze tento týden sleva až 80 % na PHP e-learning!
Využij předvánočních slev a získej od nás 20 % bodů zdarma! Více zde

Lekce 4 - Dokončení React kalkulačky

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Komponenty React kalkulačky, jsme začali programovat Rect komponenty naší jednoduché kalkulačky. Tu jsme zvolili jako dostatečně jednoduchý projekt k vyzkoušení základů React. V dnešním React tutoriálu budemem pokračovat a naši první skutečnou aplikaci zcela dokončíme! :)

src/calculator/O­perationSelec­t.js

Ostatní naše komponenty budou vypadat hodně podobně jako ty, co jsme si vytvořili minule. Jako další na řadu si vezmeme komponentu pro výběr operace:

import React, { Component } from 'react';

export default class OperationSelect extends Component {
    constructor(props) {
        super(props);
        const value = this.props.value;
        this.state = { value: value ? value : '' };
        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(event) {
        const value = event.target.value;
        this.setState({ value });
        this.props.onChange(value ? value : null);
    }

    render() {
        const { label, name, operations } = this.props;

        const options = Object.keys(operations).map((value, index) => {
            return <option key={index} value={value}>{operations[value]}</option>
        });

        return (
            <label htmlFor={name}>
                {label}
                <select id={name} required
                    value={this.state.value}
                    onChange={this.handleChange}>
                    <option value="">--Vyberte operaci--</option>
                    {options}
                </select>
            </label>
        );
    }
}

Vidíte opět práci s vlastnostmi, stavem a jeho změnami. Co možná stojí za zmínku, je způsob vykreslení možností (option) pro seznam operací. Zde pro jejich sestavení použijeme JS map(), přičemž pro jednoduché vložení do JSX jim musíme dát jejich unikátní klíče (key=...).

src/calculator/O­peration.js

Už se nám to pěkně rýsuje, ale ještě před úpravou komponenty formuláře kalkulačky si definujeme její aktuálně podporované operace. Je to hlavně z toho důvodu, že by naše kalkulačka měla být do budoucna snadno rozšiřitelná. A jelikož nejsme barbaři, definujeme si je hezky do samostatného souboru:

const Operation = Object.freeze({
    ADD: 'add',
    SUBTRACT: 'subtract',
    MULTIPLY: 'multiply',
    DIVIDE: 'divide'
});

export default Operation;

Pokud umíte JS, tak k tomu snad není co dodat.

src/calculator/Cal­culatorForm.js

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

A zlatým hřebem bude samotná komponenta pro formulář kalkulačky, kde veškerou předchozí funkcionalitu propojíme a také zde definujeme naše výpočty.

V minulé lekci už jsme si do této komponenty přidali obsluhu zadání hodnot operandů do číselných políček, podobně si teď doplníme obsluhu pro výběr operátoru. Jednotlivé operátory definujeme opět v konstruktoru a později při vykreslení je předáme instanci komponenty OperationSelect. Samotný výpočet pak provedeme v nové obslužné metodě pro stisk tlačítka odeslání formuláře handleSubmit() a tuto obsluhu přiřadíme elementu <form> v atributu onSubmit. Celý kód včetně importů a kosmetických úprav (popisků) vykreslených elementů bude vypadat následovně:

import React, { Component } from 'react';
import NumberInput from './NumberInput';
import Operation from './Operation';
import OperationSelect from './OperationSelect';

export default class CalculatorForm extends Component {
    constructor(props) {
        super(props);
        this.operations = {
            [Operation.ADD]: 'Sčítání',
            [Operation.SUBTRACT]: 'Odčítání',
            [Operation.MULTIPLY]: 'Násobení',
            [Operation.DIVIDE]: 'Dělení'
        };
        this.state = { x: 0, y: 0, operation: null, result: null };

        const handleChange = (name, value) => this.setState({ [name]: value });
        this.handleChangeX = handleChange.bind(this, 'x');
        this.handleChangeY = handleChange.bind(this, 'y');
        this.handleChangeOperation = handleChange.bind(this, 'operation');
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    calculate() {
        const { x, y, operation } = this.state;
        switch (operation) {
            case Operation.ADD: return x + y;
            case Operation.SUBTRACT: return x - y;
            case Operation.MULTIPLY: return x * y;
            case Operation.DIVIDE: return x / y;
            default: return null; // Sem by to nikdy nemělo dojít.
        }
    }

    handleSubmit(event) {
        event.preventDefault();
        const result = this.calculate();
        this.setState({ result });
        this.props.onResultChange(result);
    }

    render() {
        return (
            <form className="CalculatorForm" onSubmit={this.handleSubmit}>
                <NumberInput name="x" label="První číslo:"
                    value={this.state.x}
                    onChange={this.handleChangeX} />
                <NumberInput name="y" label="Druhé číslo:"
                    value={this.state.y}
                    onChange={this.handleChangeY} />
                <OperationSelect name="operation" label="Operace:"
                    operations={this.operations}
                    value={this.state.operation}
                    onChange={this.handleChangeOperation} />
                <input type="submit" value="Spočítej" />
            </form>
        );
    }
}

Na první pohled to vypadá možná trochu komplikovaně, ale ve skutečnosti zde není nic, co bychom už neznali :) Je zde definice stavu, operací, výpočtu výsledku a jeho propagace při odeslání formuláře pomocí události onSubmit.

Princip je takový, že díky propagaci stavů komponent vždy víme o hodnotách v nich uložených. Pokud pak uživatel formulář odešle, zamezíme výchozí akci pomocí event.preventDefault() a následně z hodnot spočítáme výsledek, který dále propagujeme.

src/App.js

Nakonec ještě zajistíme předání výsledku do komponenty pro jeho výpis v rámci naší aplikace:

import React, { Component } from 'react';
import CalculatorForm from './calculator/CalculatorForm';
import Result from './calculator/Result';
import './App.css';

export default class App extends Component {
    constructor(props) {
        super(props);
        this.state = { result: null };
        this.propagateResult = result => this.setState({ result });
    }

    render() {
        const title = 'React kalkulačka';

        return (
            <div className="App">
                <h1>{title}</h1>
                <CalculatorForm onResultChange={this.propagateResult} />
                <Result value={this.state.result} />
            </div>
        );
    }
}

Tady už by také nemělo být nic překvapivého :)

Styly

Tímto je práce na komponentách hotova, ale my si ještě na závěr doplňme CSS, aby naše aplikace alespoň trochu vypadala.

src/App.css

Zde pro jednoduchost dáme styl ke komponentě naší aplikace, protože jinde není v podstatě co stylizovat:

.App {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

label {
    display: block;
    clear: both;
    margin: 10px 0;
}

label > input, label > select {
    margin-left: 5px;
}

label > input {
    float: right;
}

input[type="submit"] {
    display: block;
    margin: 0 auto;
}

.Result {
    font-size: 1.5em;
    font-weight: bold;
    margin: 10px 0;
}

Jak vidíte v rámci CSS hezky využijeme názvy tříd našich komponent.

A tím je naše práce na celém projektu dokončena. Pokud se teď podíváte na spuštěnou aplikaci, měli byste vidět funkční kalkulačku a můžete na ní vyzkoušet všechny chytáky, které vás napadnou :)

Pokud vám není cokoli jasné, stáhněte si projekt z přílohy a projeďte si ho. Kódu v aplikaci tolik nemáme, po chvíli byste se v principu měli zorientovat.

V příloze nejsou nainstalované moduly, kvůli jejich velikost. Je tedy potřeba před spuštěním aplikace použít příkaz npm install.

To je pro tuto lekci opravdu vše. Příště, v lekci Databázový klient v React - Příprava projektu, začneme úplně novou pořádnou aplikaci za použití React knihovny. A co to bude, to se nechte překvapit! ;)


 

Stáhnout

Staženo 56x (147.87 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

 

Článek pro vás napsal Jindřich Máca
Avatar
Jak se ti líbí článek?
1 hlasů
Autor se věnuje převážně webovým technologiím, ale má velkou zálibu ve všem vědeckém, nejen ze světa IT. :-)
Předchozí článek
Komponenty React kalkulačky
Všechny články v sekci
React
Miniatura
Následující článek
Databázový klient v React - Příprava projektu
Aktivity (4)

 

 

Komentáře

Avatar
Tomáš Chocenský:7. června 20:25

Ahoj
Děkuji za skvělý úvod do Reactu. Chci se zeptat zda bude tato sekce pokračovat tvorbou webové aplikace k RESTful API v Node.js? Jak je slíbeno v poslední lekci o Node.js.
viz.: "Dalším krokem je postavit nad tím webovou aplikaci. Tutoriály k této problematice se objeví zde na síti v sekcích Angular a React."
Popřípadě kdy ji mohu očekávat?

S pozdravem
Tomáš

PS. předem děkuji za odpověď.

 
Odpovědět
7. června 20:25
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
mcihak
Člen
Avatar
mcihak:27. srpna 21:33

Hezký úvod do Reactu. Pracuji s Reactem už více než dva roky a tak jsem si říkal, že určitě v článku najdu nějaké nedostatky. Ale po přečtení prvních 4 lekcí musím přiznat, že jsem žádné významné neobjevil :) Určitě přeču i další díly, jsem zvědavý jak se autor "popere" s pokročilejšími tématy (např. lifecycle metody).

 
Odpovědět
27. srpna 21:33
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.