zoukankan      html  css  js  c++  java
  • React教程:4 个 useState Hook 示例

    摘要: React示例教程。

    到 React 16.8 目前为止,如果编写函数组件,然后遇到需要添加状态的情况,咱们就必须将组件转换为类组件。

    编写 class Thing extends React.Component,将函数体复制到render()方法中,修复缩进,最后添加需要的状态。

    今天,可以使用 Hook 获得相同的功能,并为自己节省了工作时间。在本文中,主要介绍useState hook。

    useState 做啥子的

    useState hook 允许咱们向函数组件添加状态,我们通常称这些为“ hooks”,但它们实际上是函数,与 React 16.8 捆绑在一起。 通过在函数组件中调用useState,就会创建一个单独的状态。

    在类组件中,state 总是一个对象,可以在该对象上添加保存属性。

    对于 hooks,state 不必是对象,它可以是你想要的任何类型-数组、数字、布尔值、字符串等等。每次调用useState都会创建一个state块,其中包含一个值。

    示例1:使用 useState 显示/隐藏组件

    这个示例是一个组件,它显示一些文本,并在末尾显示一个read more链接,当单击链接时,它展开剩下的文本。

        import React, { useState } from 'react';
        import ReactDOM from 'react-dom';
        
        // 两个 props:
        //   text - 显示的内容
        //   maxLength - 在点击“read more”之前显示多少个字符
        function LessText({ text, maxLength }) {
          // 创建一个状态,并将其初始化为“true”
          const [hidden, setHidden] = useState(true);
        
    
          if (text <= maxLength) {
            return <span>{text}</span>;
          }
        
          return (
            <span>
              {hidden ? `${text.substr(0, maxLength).trim()} ...` : text}
              {hidden ? (
                <a onClick={() => setHidden(false)}> read more</a>
              ) : (
                <a onClick={() => setHidden(true)}> read less</a>
              )}
            </span>
          );
        }
        
        ReactDOM.render(
          <LessText
            text={`专注、努力是成功的真正关键。把你的眼睛盯在目标上,然后朝着目标迈出下一步`}
            maxLength={35}
          />,
          document.querySelector('#root')
        );
    

    仅用一行代码,我们就使这个函数组件有状态:

        const [hidden, setHidden] = useState(true);
    

    但是这个函数到底在做什么呢?如果每次渲染都调用它(确实如此),它又是如何保留状态的。

    Hooks 实现的技巧

    这里的“神奇”之处是,React在每个组件的幕后维护一个对象,并且在这个持久对象中,有一个“状态单元”数组。当你调用useState时,React将该状态存储在下一个可用的单元格中,并递增数组索引。

    假设你的 hooks 总是以相同的顺序调用(如果遵循 hooks 的规则,它们将是相同的顺序),React能够查找特定useState调用的前一个值。对useState的第一个调用存储在第一个数组元素中,第二个调用存储在第二个元素中,依此类推。

    这也不是很神奇的事情,主要它依赖于你可能没有想过的事实:咱们写的的组件是由React调用 ,所以它可以在调用组件之前事先做好一些工作。 而且,渲染组件的行为不仅仅是函数调用。 像<Thing />这样的JSX被编译为React.createElement(Thing) - 显然 React 可以控制它的调用方式和时间。

    示例2:根据之前的状态更新状态

    看看另一个例子:根据前一个值更新state的值。

    咱们要造个计步器,每点击一次按钮,就计一次,点击完后,它会告诉你你走了多少步。

        import React, { useState } from 'react';
        
        function StepTracker() {
          const [steps, setSteps] = useState(0);
        
          function increment() {
            setSteps(steps => steps + 1);
          }
        
          return (
            <div>
              总共走了 {steps} 步!
              <br />
              <button onClick={increment}>
                点点我,步数不是个事!
              </button>
            </div>
          );
        }
        
        ReactDOM.render(
          <StepTracker />,
          document.querySelector('#root')
        );
    

    首先,通过调用useState创建一个新的state,并将其初始化为0。它返回steps的当前值0setSteps函数来更新 steps,用 increment函数来对steps进行增 1 操作。

    这里还可以优化的提取increment函数,可以直接将 increment 函数里面的内联到 onClick 里面:

        <button onClick={() => setSteps(steps => steps + 1)}>
          I took another step
        </button>
    

    示例3: state 作为数组

    记住,state可以保存任何你想要的值。下面是一个随机数列表的例子,单击按钮将向列表添加一个新的随机数:

        function RandomList() {
          const [items, setItems] = useState([]);
        
          const addItem = () => {
            setItems([
              ...items,
              {
                id: items.length,
                value: Math.random() * 100
              }
            ]);
          };
        
          return (
            <>
              <button onClick={addItem}>Add a number</button>
              <ul>
                {items.map(item => (
                  <li key={item.id}>{item.value}</li>
                ))}
              </ul>
            </>
          );
        }
    

    注意,我们state初始化为空数组[],并在addItem函数中更新值。

    setItems 更新 state 不会将旧值“合并” - 它会使用新值覆盖state。 这与this.setState在类中的工作方式不同。

    示例4:具有多个键的 state

    再来看看,state为对象的例子,创建一个包含2个字段的登录表单:usernamepassword

    下面示例主要展示如何在一个state对象中存储多个值,以及如何更新单个值。

        function LoginForm() {
          const [form, setValues] = useState({
            username: '',
            password: ''
          });
        
          const printValues = e => {
            e.preventDefault();
            console.log(form.username, form.password);
          };
        
          const updateField = e => {
            setValues({
              ...form,
              [e.target.name]: e.target.value
            });
          };
        
          return (
            <form onSubmit={printValues}>
              <label>
                Username:
                <input
                  value={form.username}
                  name="username"
                  onChange={updateField}
                />
              </label>
              <br />
              <label>
                Password:
                <input
                  value={form.password}
                  name="password"
                  type="password"
                  onChange={updateField}
                />
              </label>
              <br />
              <button>Submit</button>
            </form>
          );
        }
    

    如果想试试,可查看 CodeSandbox

    首先,我们创建一个state片段,并用一个对象初始化它

        const [form, setValues] = useState({
          username: '',
          password: ''
        })
    

    这看起来像是在类中初始化状态的方式。

    还有一个处理提交的函数,其中,e.preventDefault来阻止页面刷新并打印出表单值。

    updateField函数更有意思。它使用setValues传递一个对象,为了确保现有的状态不被覆盖,这里使用了展开运算(...form)。

    代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

    原文:https://daveceddia.com/usestate-hook-examples/

    关于Fundebug

    Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了20亿+错误事件,付费客户有阳光保险、核桃编程、荔枝FM、掌门1对1、微脉、青团社等众多品牌企业。欢迎大家免费试用

  • 相关阅读:
    java学习笔记
    androd Sdk manager配置
    50ms延时程序
    89c51中断入口地址表
    打印杨辉三角--队列的应用
    栈的应用--括号匹配
    哈夫曼编码---数据压缩
    PS转手绘
    数据结构学习思路
    第三届蓝桥杯省赛---第39级台阶
  • 原文地址:https://www.cnblogs.com/fundebug/p/4-react-usestate-hook-examples.html
Copyright © 2011-2022 走看看