未加星标

Stateful and stateless components, the missing manual

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二05 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏

The goals of this article are to define what stateful and stateless components are, otherwise known as smart and dumb - or container and presentational components. For the purposes of the article, we’ll be using Angular 2 Components to explain the stateful/stateless concepts. Bear in mind these concepts are not at all limited to Angular at all, and live in other libs/frameworks such as React.

Table of contents Impure versus Pure functions Impure functions (stateful) Pure functions (stateless) Stateful Todo component Stateless TodoForm component Stateless TodoList component Terminology

Before we begin, let’s clarify what “stateful” and “stateless” really mean in programming terms.

Stateful

When something is “stateful”, it is a central point that stores information in memory about the app/component’s state. It also has the ability to change it. It is essentially a “living” thing that has knowledge of past, current and potential future state changes.

Stateless

When something is “stateless”, it calculates its internal state but it never directly mutates it. This allows for complete referential transparency meaning that given the same inputs, it will always produce the same output. These are not essentially “living” as they are merely passed information. This means it has no knowledge of the past, current or future state changes.

Components

When we talk about stateful and stateless in web application development, we can begin to apply these concepts to component paradigms. So what is a component? A component is an isolated piece of behaviour or functionality that allows us to divide behaviour into roles, much like we would with javascript functions.

Impure versus Pure functions

When we think about stateful and stateless components, we can ignore any framework entirely until it comes to implementation and think about JavaScript functions. Let’s first consider pure versus impure functions, and somewhat compare them to stateful and stateless. I really like comparing component types to functions to better understand UI composition.

In my eyes, after reading this you’ll match up:

Impure Function = Stateful Component Pure Function = Stateless Component

Check out my Pure versus Impure functions article for more depth, but we’ll cover the basics here.

Impure functions (stateful)

Let’s consider the following code from the above article, which parses the user’s weight and height values into Number types, then calculates the bmi (Body Mass Index) based on the formula.

const weight = parseInt(form.querySelector('input[name=weight]').value, 10); const height = parseInt(form.querySelector('input[name=height]').value, 10); const bmi = (weight / (height /100 * height / 100)).toFixed(1);

This is great in terms of the fact that it works, however this doesn’t create a reusable function that allows us to calculate the BMI elsewhere, test the formula easily, and relies on very procedural code. Let’s look at how we can make it “pure”. The important piece here is that this chunk of code is the driver of changes, and we can rely on pure functions to essentially create small isolated pieces of logic that accept data and return new data without relying on external variables.

Pure functions (stateless)

When we think about pure functions, we would be able to expect the same result every time, without the knowledge of lexical constant values such as weight or height . Let’s refactor the formula to be a pure function:

const weight = form.querySelector('input[name=weight]').value; const height = form.querySelector('input[name=height]').value; const getBMI = (weight, height) => { let newWeight = parseInt(weight, 10); let newHeight = parseInt(height, 10); return (newWeight / (newHeight /100 * newHeight / 100)).toFixed(1); }; const bmi = getBMI(weight, height);

The getBMI function can easily live elsewhere, not necessarily in the same function (as this example is inside the onSubmit ) function if you check the other article. Now the function is pure, it can be defined better in terms of “why”. The function has several attributes:

It can be easily tested with mocked data It can be re-used multiple times to perform the role it has been given It has a defined input (function arguments) It has a defined output ( return statement with new data)

Here’s the thing: all four of the above concepts directly map across to thinking about stateless components.

Let’s now take the “impure” functions and look at the stateful component equivalent, followed by the “pure” functions that can be mapped across to stateless components.

Stateful components

Much like an impure JavaScript function, a stateful component is the driver of what happens, and it therefore utilises any stateless components at our disposal.

Here are some attributes that a stateful component has:

Drives state changes through functions Provides data (i.e. from http layers) May receive initial data viaroute resolves instead of service layer calls Has living knowledge of the current state Is informed by stateless components when something needs to change Can communicate with external dependencies (such as an http layer) Renders child stateless (or even stateful) components, perhaps within with a single <div> wrapper for layout containment Contain Redux actions (ngrx/store or ng2redux for example)

This list, and the one further in the article, was inspired by Dan Abramov’s Presentational and Container components article.

Stateful Todo component

In this article, we’re going to build a small todo application demonstrating these concepts, followed by their stateless counterparts.

First, let’s start off by rendering our base component, the <app> to kick things off:

import { Component } from [email protected]/core'; @Component({ selector: 'my-app', template: ` <todos></todos> ` }) export class AppComponent { }

Inside here, we’re rendering a <todos> component. This component will be stateful, let us continue! We’re not going to teach how to build a todo app, we all know this, so we’re going to look at how we can apply stateful and stateless paradigms to Angular 2 components and observe the ideas.

Let’s look at the component composition through ASCII art as we progress, so far we have an <app> component:

┌─────────────────┐ │ <app> │ └─────────────────┘

Now onto the <todos> component:

import { Component, OnInit } from [email protected]/core'; import { TodoService } from './todo.service'; @Component({ selector: 'todos', template: ` <div> <todo-form (onAdd)="addTodo($event)"> </todo-form> <todo-list [todos]="todos" (onComplete)="completeTodo($event)" (onDelete)="removeTodo($event)"> </todo-list> </div> ` }) export class TodosComponent implements OnInit { todos: any[]; constructor(private todoService: TodoService) {} ngOnInit() { this.todos = this.todoService.getTodos(); } addTodo({label}) { this.todos = [{label, id: this.todos.length + 1}, ...this.todos]; } completeTodo({todo}) { this.todos = this.todos.map( item => item.id === todo.id ? Object.assign({}, item, {complete: true}) : item ); } removeTodo({todo}) { this.todos = this.todos.filter(({id}) => id !== todo.id); } } You can see from the above that all we have is a container <div> wrapping two further child (stateless) components. There is no other logic in the template other than that. The <todo-form> component receives no input, but expects to bind an output called onAdd . Next up, the <todo-list> component receives the todos data from the [todos] input binding, and two outputs (onComplete) and (onDelete) , delegating the respective functions to the stateless counterparts.

The rest of the component class are the methods that make up the functionality of the todo component. Immutable operations are taking place inside each callback, and each callback is exposed to a stateless component so that it can run with it. All these functions are expecting is a notification that something has changed, for instance “Oh hey! Here’s a new todo label, go ahead and do your thing with it oh-mighty stateful component”. Note how the functions are only called from the child, stateless, level.

And that’s literally it on stateful. We cover some of the potential concepts that stateful components may contain. Let’s move onto the more frequently used stateless components.

ASCII (the TodoService represents the injected Service):

┌─────────────────┐ │ <app> │ └────────┬────────┘ %

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

主题: JavaJavaScriptReact
分页:12
转载请注明
本文标题:Stateful and stateless components, the missing manual
本站链接:http://www.codesec.net/view/481695.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(37)