A talk by Leonid Shevtsov.
?
for help,
p
for notes.
Talks catalog
::
Back to site
.
class: center, middle # React / Redux ### Leonid Shevtsov for BrightBytes, July 2016. <img src="/uploads/images/react_talk/react.png" style="width:40%" /> <img src="/uploads/images/react_talk/redux.png" style="width:40%" /> ??? This isn't going to be a comprehensive overview of React, or Redux. I'm giving you the good parts, or rather, my favorite parts. I wrote apps in React, and in Clojurescript in re-frame, and Om. I think right now this is the most effective way to make rich web apps. But it does demand a paradigm shift to "get it". When I first saw React on a client project, I was like "what is this? Angular is so much better! i want my two-way data binding!" and so on. To appreciate React, I had to understand that it is a functional library, and all the benefits thereof, which I'd like to talk about. --- class: center, middle # React <img src="/uploads/images/react_talk/react.png" style="width:40%" /> ??? Let's start with a history lesson. Before we had dynamic web pages, life was simple: you rendered some templates on the backend, done. If you had new data to display, you just rendered a new page. The first generation of dynamic pages was spaghetti DOM manipulation and jQuery. The second was object-oriented libraries, representing each element of the page as an object that managed its state and took care of redrawing itself. Problems arose when we had to share and communicate mutable state across multiple objects on the page, and implement complex asynchronous updates. React brings us back to the simpler times by letting us declare the webpage as a _function_ of _immutable state_, and, under the hood, it handles the abstraction of updating the page when the state, inevitably, changes. In essense, this lets us reason about webpages as if they _never_ change. This is not a trick, nor a disguised rehash of the existing object-oriented approach. This is fundamentally a different way to think about UI - the functional way. But it's also a very familiar way - it's just like we make static pages. --- class: center, middle # Redux <img src="/uploads/images/react_talk/redux.png" style="width:40%" /> ??? While you can make simple apps using just React, it doesn't give you any facilities to manage complex state. This is where Redux comes in. Redux is a state management machine. To continue the web1.0 analogy, it plays the role of the "backend". Redux gives you three things: - a singleton _application state_, functionally immutable. - a singleton _action queue_ and a way to put _action objects_ into it that represent events as values. - a way to write and compose _reducer functions_, which take in the current application state, and an action object, and return a _new_ application state. (Reducing, of course, comes from functional programming.) --- # The data loop ``` You set the initial State | |->"Container" components map the State into Props | | | "Presentational" components render Props into markup (Virtual DOM) | | | React applies the virtual DOM to the Real DOM | | ^ v (User performs interaction) | | | The browser event handler dispatches an Action Object to Redux | | | Redux calls Reducers to combine the action object | | and the current state into a new State | | | | (And the cycle repeats forever) |<-| ``` ??? Let's look at how Redux and React work together in what is called the "data loop". (Note that there is just one loop in the entire application.) First, you boot the application. This includes: setting the initial state, assigning a top-level React component, and a top-level reducer function. Then the state is fed to the top-level React component to generate DOM. Modern React idioms discern two kinds of components. Presentational components are pure templates that render data from props (arguments) into markup. (Prime candidates for our CommonUI!) Container components map application state into data for presentational components, and produce event handlers that tie into the dispatcher. They don't contain any markup. ... Naturally, UI event handlers dispatch Action Objects. Action Objects are plain old javascript hashes, and "dispatch" means "call a library function". The event handlers are not allowed to do anything else. Redux takes the action object, takes the current state, and calls the top-level reducer function to produce a new state. Then the new state is taken to the top-level React component, and the functional Ouroboros bites its tail. --- # Async operations ``` You click "Create" | | (A server request is needed to persist the data) | On click, an Async Action Creator is dispatched | The Async Action Creator dispatches a | "Form is being saved" action object | The Async Action Creator sends an AJAX request | | (Time passes) | The AJAX request is complete. Its promise handler | dispatches a "Form is saved" action object, with | data received from the server | Redux calls Reducers, and they use the new data to update the state (maybe insert the new object into a list) ``` ??? But what about asynchronoous operations, you say? That's the most problematic problem of all! The caveat of FP is that pure functional code can't do anything but return a value. That's why for async operations Redux provides a dirty trick, dirty and common. Say you want to create a new entity on the server. Then, instead of an action object, you dispatch an _Async Action Creator_ - a function that can do anything, but eventually should dispatch one or more Action Objects. Typically, it dispatches a "request started" action, then makes an AJAX call, then once that is complete it dispatches a "request complete" action. - The async code never mutates anything. - The effect of the async operation - dispatched action objects - is easy to specify and test. - Conversely, the effect of the async operation is easy to stub. - It's also easy to rewind and replay, more about this later. Now is a good time to say that you can dispatch almost anywhere in your code, theoretically - everywhere but reducers. But I mean, from timers, initialization code, etc. --- # What's in it for me? .right[*- A concerned UI designer*] - Simpler, more straightforward templating - develop markup as if the page is static. - Since presentational components only depend on their props, you can have many copies of the same component on the page, representing all possible states. - Separation of presentational components from business logic means you can fully own your part of the application. - Instead of coding HTML that is then going to be obscured by code and hard to inspect and modify, you can write presentational components that will be always easily accessible, even when integrated into the application. --- # What's in it for me? .right[*- A world-weary frontend engineer*] - Separation of mutation from asynchronicity. - Reduction of mutation to (uhh) reduction. - Separation of view from business logic. - No more programming in ng-html. - Easy unit testing. - Remarkable support for live reload. - Where is my data? There it is. --- # Cool tools - https://github.com/gaearon/redux-devtools - https://github.com/steos/reactcards .center[<img src="https://camo.githubusercontent.com/a0d66cf145fe35cbe5fb341494b04f277d5d85dd/687474703a2f2f692e696d6775722e636f6d2f4a34476557304d2e676966" width="60%"/>] ??? Since all state changes in the application are driven by action objects, if you store a list of all action objects you can rewind and replay your application behavior. The redux-devtools project does just that. Just think about it - everything that happens in the application, happens because of an action object. There's no other way. If you see something unexpected, it's very easy to isolate it to a specific reducer branch, and a specific dispatch location. Redux-devtools can also inspect state. Reactcards is a documentation/live coding tool. It resembles our commonui demo app. You comment your components with examples and reactcards renders live reloading pages with these examples. --- # PROTIPs - Don't think of components as objects. They are functions. Object-oriented components, with state, must be an exception. (One usecase is very low-level ui components.) - Use Immutable.JS to make state truly immutable http://facebook.github.io/immutable-js/ - it reduces bugs and does not hurt performance. - Selectors are an efficient way to express non-trivial state-prop mappings (Think huge filterable or sortable list.) https://github.com/reactjs/reselect --- # Beyond - http://elm-lang.org - https://github.com/Day8/re-frame ??? React is a good mainstream library for familiar and welcome Javascript. But there are reasons to go beyond JS, at least for inspiration, as the author of Redux did, by the way. Or if you are writing a one-man project and need to be as productive as possible. Elm is a fully functional strongly typed front-end language inspired by Haskell. It uses the same data loop concept. Clojurescript has multiple React-inspired and React-driven frameworks. That's because the immutability and homoiconicity of Clojure pairs to React better than wine to cheese. And Clojurescript is _the_ most robust and capable front-end language (after Javascript). --- # Thanks! - https://facebook.github.io/react/docs/thinking-in-react.html https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.teb3u8hbn