react hooks入门详细教程

State Hooks

案例:

import { useState } from 'react';

function Example() {
 const [count, setCount] = useState(0);
//count:声明的变量;setCount:改变count值的函数;0:count的初始值
 return (
  <div>
   <p>You clicked {count} times</p>
   <button onClick={() => setCount(count + 1)}>
    Click me
   </button>
  </div>
 );
}

useState是react自带的一个hook函数,它的作用就是用来声明状态变量。useState这个函数接收的参数是我们的状态初始值(initial state),它返回了一个数组,这个数组的第[0]项是当前当前的状态值,第[1]项是可以改变状态值的方法函数。
所以我们做的事情其实就是,声明了一个状态变量count,把它的初始值设为0,同时提供了一个可以更改count的函数setCount

当用户点击按钮时,我们调用setCount函数,这个函数接收的参数是修改过的新状态值。接下来的事情就交给react了,react将会重新渲染我们的Example组件,

假如一个组件有多个状态值怎么办?
首先,useState是可以多次调用的,所以我们完全可以这样写:

function ExampleWithManyStates() {
 const [age, setAge] = useState(42);
 const [fruit, setFruit] = useState('banana');
 const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
}

其次,useState接收的初始值没有规定一定要是string/number/boolean这种简单数据类型,它完全可以接收对象或者数组作为参数。唯一需要注意的点是,之前我们的this.setState做的是合并状态后返回一个新状态,而useState是直接替换老状态后返回新状态

hook,一方面它是直接用在function当中,而不是class;另一方面每一个hook都是相互独立的,不同组件调用同一个hook也能保证各自状态的独立性。

react是怎么保证多个useState的相互独立的?

答案是,react是根据useState出现的顺序来定的。我们具体来看一下

//第一次渲染
 useState(42); //将age初始化为42
 useState('banana'); //将fruit初始化为banana
 useState([{ text: 'Learn Hooks' }]); //...

 //第二次渲染
 useState(42); //读取状态变量age的值(这时候传的参数42直接被忽略)
 useState('banana'); //读取状态变量fruit的值(这时候传的参数banana直接被忽略)
 useState([{ text: 'Learn Hooks' }]); //...

react规定我们必须把hooks写在函数的最外层,不能写在ifelse等条件语句当中,来确保hooks的执行顺序一致。

Effect Hooks

案例:

import { useState, useEffect } from 'react';

function Example() {
 const [count, setCount] = useState(0);

 // 类似于componentDidMount 和 componentDidUpdate:
 useEffect(() => {
  // 更新文档的标题
  document.title = `You clicked ${count} times`;
 });

 return (
  <div>
   <p>You clicked {count} times</p>
   <button onClick={() => setCount(count + 1)}>
    Click me
   </button>
  </div>
 );
}

假如不用hooks,我们会怎么写?

class Example extends React.Component {
 constructor(props) {
  super(props);
  this.state = {
   count: 0
  };
 }

 componentDidMount() {
  document.title = `You clicked ${this.state.count} times`;
 }

 componentDidUpdate() {
  document.title = `You clicked ${this.state.count} times`;
 }

 render() {
  return (
   <div>
    <p>You clicked {this.state.count} times</p>
    <button onClick={() => this.setState({ count: this.state.count + 1 })}>
     Click me
    </button>
   </div>
  );
 }
}

我们写的有状态组件,通常会产生很多的副作用(side effect),比如发起ajax请求获取数据,添加一些监听的注册和取消注册,手动修改dom等等。我们之前都把这些副作用的函数写在生命周期函数钩子里,比如componentDidMount,componentDidUpdate和componentWillUnmount。而现在的useEffect就相当与这些声明周期函数钩子的集合体。它以一抵三。

useEffect怎么解绑一些副作用?

传给useEffect的副作用函数返回一个新的函数即可。这个新的函数将会在组件下一次重新渲染之后执行。

import { useState, useEffect } from 'react';

function FriendStatus(props) {
 const [isOnline, setIsOnline] = useState(null);

 function handleStatusChange(status) {
  setIsOnline(status.isOnline);
 }

 useEffect(() => {
  ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
  // 一定注意下这个顺序:告诉react在下次重新渲染组件之后,同时是下次调用ChatAPI.subscribeToFriendStatus之前执行cleanup
  return function cleanup() {
   ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
  };
 });

 if (isOnline === null) {
  return 'Loading...';
 }
 return isOnline ? 'Online' : 'Offline';
}

怎么跳过一些不必要的副作用函数?

按照上一节的思路,每次重新渲染都要执行一遍这些副作用函数,显然是不经济的。怎么跳过一些不必要的计算呢?我们只需要给useEffect传第二个参数即可。用第二个参数来告诉react只有当这个参数的值发生改变时,才执行我们传的副作用函数(第一个参数)。

useEffect(() => {
 document.title = `You clicked ${count} times`;
}, [count]); // 只有当count的值发生变化时,才会重新执行`document.title`这一句

当我们第二个参数传一个空数组[]时,其实就相当于只在首次渲染的时候执行。也就是componentDidMount加componentWillUnmount的模式。不过这种用法可能带来bug,少用。

还有哪些自带的Effect Hooks?

useContext
useReducer
useCallback
useMemo
useRef
useImperativeMethods
useMutationEffect
useLayoutEffect

怎么写自定义的Effect Hooks?

为什么要自己去写一个Effect Hooks? 这样我们才能把可以复用的逻辑抽离出来,变成一个个可以随意插拔的“插销”,哪个组件要用来,我就插进哪个组件里

比如我们可以把上面写的FriendStatus组件中判断朋友是否在线的功能抽出来,新建一个useFriendStatus的hook专门用来判断某个id是否在线。

import { useState, useEffect } from 'react';

function useFriendStatus(friendID) {
 const [isOnline, setIsOnline] = useState(null);

 function handleStatusChange(status) {
  setIsOnline(status.isOnline);
 }

 useEffect(() => {
  ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
  return () => {
   ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
  };
 });

 return isOnline;
}

这时候FriendStatus组件就可以简写为:

function FriendStatus(props) {
 const isOnline = useFriendStatus(props.friend.id);

 if (isOnline === null) {
  return 'Loading...';
 }
 return isOnline ? 'Online' : 'Offline';
}

假如这个时候我们又有一个朋友列表也需要显示是否在线的信息:

function FriendListItem(props) {
 const isOnline = useFriendStatus(props.friend.id);

 return (
  <li style={{ color: isOnline ? 'green' : 'black' }}>
   {props.friend.name}
  </li>
 );
}

这样就实现了组件复用

taro hooks

在 Taro 中使用 Hooks API 很简单,Taro 的专有 Hooks(例如 usePageScroll, useReachBottom)从 @tarojs/taro 中引入,框架自己的 Hooks (例如 useEffect, useState)从对应的框架引入。

import { usePageScroll, useReachBottom } from '@tarojs/taro' // Taro 专有 Hooks
import { useState, useEffect } from 'react' // 框架 Hooks (基础 Hooks)

到此这篇关于react hooks入门详细教程的文章就介绍到这了,更多相关react hooks入门内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 30分钟精通React今年最劲爆的新特性——React Hooks

    你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗? --拥有了hooks,你再也不需要写Class了,你的所有组件都将是Function. 你还在为搞不清使用哪个生命周期钩子函数而日夜难眠吗? --拥有了Hooks,生命周期钩子函数可以先丢一边了. 你在还在为组件中的this指向而晕头转向吗? --既然Class都丢掉了,哪里还有this?你的人生第一次不再需要面对this. 这样看来,说React Hooks是今年最劲爆的新特性真的毫不夸张.如果你也对react

  • react的hooks的用法详解

    hooks的作用 它改变了原始的React类的开发方式,改用了函数形式;它改变了复杂的状态操作形式,让程序员用起来更轻松;它改变了一个状态组件的复用性,让组件的复用性大大增加. useState // 声明状态 const [ count , setCount ] = useState(0); // 使用状态 <p>You clicked {count} times</p> <button onClick={()=>{setCount(count+1)}}>cli

  • React 使用Hooks简化受控组件的状态绑定

    开始之前 阅读本文需要对以下几项有一定了解 ECMAScript 6 文章中大量用到了 ES6 语法,比如解构赋值和函数参数默认值.剩余参数.展开语法.箭头函数等. Hooks React 在 16.8 版本中推出了 Hooks,它允许你在"函数组件"中使用"类组件"的一些特性. React 本身提供了一些 Hooks,比如 useState.useReducer 等.通过在一个以"use"作为命名起始的函数中调用这些 Hooks,就得到了一个

  • 如何对react hooks进行单元测试的方法

    写在前面 使用 react hook 来做公司的新项目有一段时间了,大大小小的坑踩了不少.由于是公司项目,因此必须要编写单元测试来确保业务逻辑的正确性以及重构时代码的可维护性与稳定性,之前的项目使用的是 react@15.x 的版本,使用 enzyme 配合 jest 来做单元测试毫无压力,但新项目使用的是 react@16.8 ,编写单元测试的时候,遇到不少阻碍,因此总结此篇文章算作心得分享出来. 配合 enzyme 来进行测试 首先,enzyme 对于 hook 的支持程度,可以参考这个 i

  • 一百多行代码实现react拖拽hooks

    前言 源码总共也就一百多行,看完这个大致可以理解一些成熟的react拖拽库的实现思路,比如react-dnd,然后你上手这些库的时候就非常快了. 使用hooks实现的大致效果动图如下: 我们的目标是实现一个useDrag和useDrop的hooks,类似以下用法就可以轻松让元素可以拖拽,并且在拖拽的各个生命周期,如下,可以自定义传递消息(顺便介绍几个拖拽会触发的事件). dragstart:用户开始拖拉时,在被拖拉的节点上触发,该事件的target属性是被拖拉的节点. dragenter:拖拉进

  • React Hooks的深入理解与使用

    你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗? --拥有了hooks,你再也不需要写Class了,你的所有组件都将是Function. 你还在为搞不清使用哪个生命周期钩子函数而日夜难眠吗? --拥有了Hooks,生命周期钩子函数可以先丢一边了. 你在还在为组件中的this指向而晕头转向吗? --既然Class都丢掉了,哪里还有this?你的人生第一次不再需要面对this. 这样看来,说React Hooks是今年最劲爆的新特性真的毫不夸张.如果你也对react

  • 记录一次完整的react hooks实践

    写在前面 React在16.8版本正式发布了Hooks.关注了很久,最近正好有一个小需求,赶紧来试一下. 需求描述 需求很简单,部门内部的一个数据查询小工具.大致长成下面这样: 用户首次访问页面,会拉取数据展示.输入筛选条件,点击查询后,会再次拉取数据在前端展示. 需求实现 使用React Class Component的写法 如果使用以前的class写法,简单写一下,代码可能大概长成下面这样: import React from 'react'; import { Tabs, Input, R

  • React Hooks 实现和由来以及解决的问题详解

    与React类组件相比,React函数式组件究竟有何不同? 一般的回答都是: 类组件比函数式组件多了更多的特性,比如 state,那如果有 Hooks 之后呢? 函数组件性能比类组件好,但是在现代浏览器中,闭包和类的原始性能只有在极端场景下才会有明显的差别. 性能主要取决于代码的作用,而不是选择函数式还是类组件.尽管优化策略有差别,但性能差异可以忽略不计. 参考官网:(https://zh-hans.reactjs.org/docs/hooks-faq.html#are-hooks-slow-b

  • React Hooks常用场景的使用(小结)

    前言 React 在 v16.8 的版本中推出了 React Hooks 新特性.在我看来,使用 React Hooks 相比于从前的类组件有以下几点好处: 代码可读性更强,原本同一块功能的代码逻辑被拆分在了不同的生命周期函数中,容易使开发者不利于维护和迭代,通过 React Hooks 可以将功能代码聚合,方便阅读维护: 组件树层级变浅,在原本的代码中,我们经常使用 HOC/render props 等方式来复用组件的状态,增强功能等,无疑增加了组件树层数及渲染,而在 React Hooks

  • 使用hooks写React组件需要注意的5个地方

    Hook是React16.8开始新增的特性.虽然React官方文档已经作出了针对React hooks的相关概念的讲解,但是光看官方文档是很难将hooks使用好的,在编写hooks的过程中很容易跳进陷阱和错误.本文总结了5个不好的地方. 01.不需要render的场景下使用useState 在函数组件中我们可以使用useState来管理状态,这使得对状态的管理变得很简单,但是也容易被滥用,我们通过下面的代码样例看下容易忽略的地方. 不推荐× function ClickButton(props)

随机推荐