如何用React Hook开发带状态的SPA V组件 - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 小程序相关 >

如何用React Hook开发带状态的SPA V组件

发表时间:2021-1-11

发布人:葵宇科技

浏览次数:50

把WEB UI分立为一个个带状态的 V,是一个概念革命,因为开发者工作时看到的变量语句函数,就像建筑工人上班时看到的是水泥沙石钢筋,这是一种低层次的作业水平。

把SPA看成一个个V,就像把建筑看一个个独立的生活空间,而不是水泥钢筋。所以学习造V 和Vx,就像学习造生活空间。我们工作处理的是水泥钢筋,变量语句,心中指引我们的,是生活空间,和V逻辑。

EM:把一座大厦建筑比较一个SPA,大厦的「功能空间」比作会话,具体「生活空间」比作会话步骤,是非常相似的。

前一文,我们学习了如何使用React 提供的最基本的 V制作工具—— Component 基类——制作带状态的V组件(主要使用 Component.setState API),本文将介绍React 最新V制作技术——Hook来 完成同一个任务 。本文部分内容摘自《 How To Manage State with Hooks on React Components 》。

Table of Contents

React Hook是什么技术

React Hook 的设计可以概括为一个句话,就是 让开发V组件更轻便,是对之前Component基类工具的一次革新。让开发V组件更轻便 体现在多个方面,本文「实现带本地状态的V」的useSate 和 useReducer 只是其中之一,是最基础的V功能。因为我们还要开发 提供丰富交互功能UI组件,这些复杂UI组件(Vx)需要复杂的状态控制,React提供了useEffect 和 useContext等种类Hook的支持。

为function 组件“勾选”功能

Hook 宣称 让你在不使用class的情况下编写全能的V组件——通过给 function 灵活“勾选”所需要的功能。然而,function本身只是一个无状态的类对象,让它“勾选”了状态功能后就是一个完整的对象object了:

函数本身可是一个只有方法的对象,是一个没状态的特殊对象,引入外功能,就是指将它转为一个特殊的有状态或其它功能的对象,不经过类实例化的轻便对象

这种方式还是很聪明 的。除此外还引入了一定的抽象,便利了开发。

useXXX抽象

技术上,Hook 是React提供的一个非常特殊的库功能,从它的特定使用规则就知道。例如,它必须在固定的地方按一定的顺序(必是function组件语法顶层)上使用。

另外,Hook就是为制作V Vx提供的更方便的 抽象 工具,useXXX 就是在逻辑上:

你的计算任务想要什么东西,我直接给你,你不用管了

# 两种基础的状态 Hook 工具

React Hook 提供四个主要 Hook功能 给开发者“勾选”:

  • useState
  • useReducer
  • useEffect
  • useContext

本文实例只介绍了帮助开发一类基本V(独立的私有状态的V)的两个功能Hook。

EM:我喜欢研究React Hook 提供的API,来总结 实际应用 V的种类

useState 与 简单私有状态的V组件

useState 用来开发最基本的V组件,包括简单的无记忆计算(例如加法计算器),和简单的记忆计算(例如开关按键)。

状态就是智能记忆么?

useState 与 有记忆组件是比较好理解的,例如「开关按键」的下一次点击结果取决于上一次的状态;无记忆useState则需要更多的解释,因为好像既然无记忆,还要状态干什么?其实,当用户触发一次交互,它会有一次中间计算,产生一个结果,这个结果就是「状态」,并且一般进行交互输出(产生一UI重渲染),完成一次完整的交互计算。有记忆的组件只是「中间计算参与的数据不单一」,交互功能由多种数据组成而已。

useState并不是真的无记忆,只是无中间记忆,状态在多次重渲染上保持,也是有“记忆”的。

useReducer 与 复杂私有状态的V组件

useState 和 useReducer 都是用来开发独立的私有状态的V,然而,useReducer 针对的具有更繁复业务逻辑的V组件;这繁复性,可以通过「useReducer的API使用」了解得到。

useReducer的API非常类似 Redux的工作模式,增加一个中间 Reducer 进行解耦。交互输入执行的是一个 action 对象(而不是直接调用状态更新逻辑),Reducer再根据action的具体目标进行相应的状态更新。

useEffect 与 松散形式的Vx组件

useEffect是用于制作具有松散形式的Vx组件,就是V的状态不完全是私有的,要与其它组件进行共享协作,使用部分数据从网络上获取。

useContext 与 复合Vx组件树

useContext 用于制作树层次结构Vx组件,方便父子V之间共享数据进行协作,具体略。

# 任务与需求

我们先回顾一下前一文的任务或需求,就是, 我们制作的是什么样的V或SPA程序。

我们制作的程序只有一个产品列表页,上面有一个购物车记录选购的功能,用户可将想买的商品添加上 购物车,当然也可删除错选的商品项,用户能看到每次选购到的商品,以及总消费金额。

EM:这个技术实例用作教学不是特别的优质

useState 与 简单 本地V状态

import React, { useState } from 'react';

const currencyOptions = {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
}

function getTotal(total) {
  return total.toLocaleString(undefined, currencyOptions)
}

export default function Product() {
  const [cart, setCart] = useState([]);  //<--
  const [total, setTotal] = useState(0); //<--

  function add() {
    setCart(['ice cream']);
    setTotal(5);
  }

  return(
    <div className="wrapper">
      <div>
        Shopping Cart: {cart.length} total items.
      </div>
      <div>Total: {getTotal(total)}</div>

      <div className="product"><span role="img" aria-label="ice cream">:icecream:</span></div>
      <button onClick={add}>Add</button>
      <button
        onClick={() => {
          setCart([]);
          setTotal(0);
        }}
      >
        Remove
      </button>
    </div>
  )
}

这个交互V的功能非常的简单:

  • 输入:添加 或 删除 一荐商品记录
  • 输出:显示选购商品数目,和总消费价格

技术,Product函数“勾了”两个状态变量:cart and total。

useReducer 与 繁复业务逻辑的本地V状态

import React, { useReducer } from 'react';
import './Product.css';

const currencyOptions = {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
}

function getTotal(cart) {
  const total = cart.reduce((totalCost, item) => totalCost + item.price, 0);
  return total.toLocaleString(undefined, currencyOptions)
}

...

function cartReducer(state, action) {
  switch(action.type) {
    case 'add':
      return [...state, action.product];
    case 'remove':
      const productIndex = state.findIndex(item => item.name === action.product.name);
      if(productIndex < 0) {
        return state;
      }
      const update = [...state];
      update.splice(productIndex, 1)
      return update
    default:
      return state;
  }
}

export default function Product() {
  const [cart, setCart] = useReducer(cartReducer, []);

  function add(product) {
    setCart({ product, type: 'add' });
  }

  function remove(product) {
    setCart({ product, type: 'remove' });
  }

  return(
    <div className="wrapper">
      <div>
        Shopping Cart: {cart.length} total items.
      </div>
      <div>Total: {getTotal(cart)}</div>

      <div>
        {products.map(product => (
          <div key={product.name}>
            <div className="product">
              <span role="img" aria-label={product.name}>{product.emoji}</span>
            </div>
            <button onClick={() => add(product)}>Add</button>
            <button onClick={() => remove(product)}>Remove</button>
          </div>
        ))}
      </div>
    </div>
  )
}

这个交互V的功能其实也很简单,没有充分展现useReducer的特色。

.

相关案例查看更多