Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >React hooks实践

React hooks实践

作者头像
嘿嘿嘿
发布于 2019-02-26 01:57:15
发布于 2019-02-26 01:57:15
1.4K00
代码可运行
举报
文章被收录于专栏:陈纪庚陈纪庚
运行总次数:0
代码可运行

前言

最近要对旧的项目进行重构,统一使用全新的react技术栈。同时,我们也决定尝试使用React hooks来进行开发,但是,由于React hooks崇尚的是使用(也只能使用)function component的形式来进行开发,而不是class component,因此,整个开发方式也会与之前产生比较大的差异。所以,我这里就积累了下实际项目中遇到的问题以及思考,看下能不能帮助大家少走弯路。

正文

接下来就直接进入正文。我会将项目中遇到的问题一一列举出来,并且给出解决方案。

执行初始化操作的时机

当我转到React hooks的时候,首先就遇到了这个问题:

一般来说,业务组件经常会遇到要通过发起ajax请求来获取业务数据并且执行初始化操作的场景。在使用class component编程的时候,我们就可以在class component提供的生命周期钩子函数(比如componentDidMount, constructor等)执行这个操作。可是如果转到React hooks之后,function component里是没有这个生命周期钩子函数的,那这个初始化操作怎么办呢?总不能每次遇到这种场景都使用class component来做吧?

解决方案:使用useEffect(想知道useEffect是什么的话,可以点击这里)

useEffect,顾名思义,就是执行有副作用的操作,你可以把它当成componentDidMount, componentDidUpdate, and componentWillUnmount 的集合。它的函数声明如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
useEffect(effect: React.EffectCallback, inputs?: ReadonlyArray<any> | undefined)

那么,我们在实际使用中,我们就可以使用这个来执行初始化操作。举个例子

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React, { useEffect } from 'react'

export function BusinessComponent() {
  const initData = async () => {
    // 发起请求并执行初始化操作
  }
  // 执行初始化操作,需要注意的是,如果你只是想在渲染的时候初始化一次数据,那么第二个参数必须传空数组。
  useEffect(() => {
    initData();
  }, []);

  return (<div></div>);
}

需要注意的是,这里的useEffect的第二个参数必须传空数组,这样它就等价于只在componentDidMount的时候执行。如果不传第二个参数的话,它就等价于componentDidMount和componentDidUpdate

做一些清理操作

由于我们在实际开发过程中,经常会遇到需要做一些副作用的场景,比如轮询操作(定时器、轮询请求等)、使用浏览器原生的事件监听机制而不用react的事件机制(这种情况下,组件销毁的时候,需要用户主动去取消事件监听)等。使用class Component编程的时候,我们一般都在componentWillUnmount或者componentDidUnmount的时候去做清理操作,可是使用react hooks的时候,我们如何做处理呢?

解决方案:使用useEffect第一个参数的返回值

如果useEffect的第一个参数返回了函数的时候,react会在每一次执行新的effects之前,执行这个函数来做一些清理操作。因此,我们就可以使用它来执行一些清理操作。

例子:比如我们要做一个二维码组件,我们需要根据传入的userId不断轮询地向后台发请求查询扫描二维码的状态,这种情况下,我们就需要在组件unmount的时候清理掉轮询操作。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React, { useEffect } from 'react'

export function QRCode(url, userId) {
  // 根据userId查询扫描状态
  const pollingQueryingStatus = async () => {
  }
  // 取消轮询
  const stopPollingQueryStatus = async() => {
  }

  useEffect(() => {
    pollingQueryingStatus();

    return stopPollingQueryStatus;
  }, []);

  // 根据url生成二维码
  return (<div></div>)
}

这样的话,就等价于在componentWillUnmount的时候去执行清理操作。

但是,有时候我们可能需要执行多次清理操作。还是举上面的例子,我们需要在用户传入新的userId的时候,去执行新的查询的操作,同时我们还需要清除掉旧的轮询操作。想一下怎么做比较好。

其实对这种情况,官方也已经给出了解决方案了,useEffect的第二个参数是触发effects的关键,如果用户传入了第二个参数,那么只有在第二个参数的值发生变化(以及首次渲染)的时候,才会触发effects。因此,我们只需要将上面的代码改一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React, { useEffect } from 'react'

export function QRCode(url, userId) {
  // 根据userId查询扫描状态
  const pollingQueryingStatus = async () => {
  }

  const stopPollingQueryStatus = async() => {
  }
  // 我们只是将useEffect的第二个参数加了个userId
  useEffect(() => {
    pollingQueryingStatus();

    return stopPollingQueryStatus;
  }, [userId]);

  // 根据url生成二维码
  return (<div></div>)
}

我们只是在useEffect的第二个参数数组里,加入了一个userId。这样的话,userId的每一次变化都会先触发stopPollingQueryStatus,之后再执行effects,这样就可以达到我们的目的。

useState与setState的差异

react hooks使用useState来代替class Component里的state。可是,在具体开发过程中,我也发现了一些不同点。useState介绍可以点击这里

在setState的时候,我们可以只修改state中的局部变量,而不需要将整个修改后的state传进去,举个例子

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React, { PureComponent } from 'react';

export class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      name: 'cjg',
      age: 18,
    }
  }

  handleClick = () => {
    const { count } = this.state;
    // 我们只需要传入修改的局部变量
    this.setState({
      count: count + 1,
    });
  }

  render() {
    return (
      <button onClick={this.handleClick}></button>
    )
  }
}

而使用useState后,我们修改state必须将整个修改后的state传入去,因为它会直接覆盖之前的state,而不是合并之前state对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React, { useState } from 'react';

export function Count() {
  const [data, setData] = useState({
    count: 0,
    name: 'cjg',
    age: 18,
  });
    
  const handleClick = () => {
    const { count } = data;
    // 这里必须将完整的state对象传进去
    setData({
      ...data,
      count: count + 1,
    })
  };

  return (<button onClick={handleClick}></button>)
}

减少不必要的渲染

在使用class Component进行开发的时候,我们可以使用shouldComponentUpdate来减少不必要的渲染,那么在使用react hooks后,我们如何实现这样的功能呢?

解决方案:React.memouseMemo

对于这种情况,react当然也给出了官方的解决方案,就是使用React.memo和useMemo。

React.memo

React.momo其实并不是一个hook,它其实等价于PureComponent,但是它只会对比props。使用方式如下(用上面的例子):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React, { useState } from 'react';

export const Count = React.memo((props) => {
  const [data, setData] = useState({
    count: 0,
    name: 'cjg',
    age: 18,
  });
  
  const handleClick = () => {
    const { count } = data;
    setData({
      ...data,
      count: count + 1,
    })
  };

  return (<button onClick={handleClick}>count:{data.count}</button>)
});
useMemo

useMemo它的用法其实跟useEffects有点像,我们直接看官方给的例子

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function Parent({ a, b }) {
  // Only re-rendered if `a` changes:
  const child1 = useMemo(() => <Child1 a={a} />, [a]);
  // Only re-rendered if `b` changes:
  const child2 = useMemo(() => <Child2 b={b} />, [b]);
  return (
    <>
      {child1}
      {child2}
    </>
  )
}

从例子可以看出来,它的第二个参数和useEffect的第二个参数是一样的,只有在第二个参数数组的值发生变化时,才会触发子组件的更新。

总结

一开始在从class component转变到react hooks的时候,确实很不适应。可是当我习惯了这种写法后,我的心情如下:

当然,现在react hooks还是在alpha阶段,如果大家觉得不放心的话,可以再等等。反正我就先下手玩玩了哈哈哈。

本文地址在->本人博客地址, 欢迎给个 start 或 follow

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-01-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
React Hooks 解析(下):进阶
React Hooks 是从 v16.8 引入的又一开创性的新特性。第一次了解这项特性的时候,真的有一种豁然开朗,发现新大陆的感觉。我深深的为 React 团队天马行空的创造力和精益求精的钻研精神所折服。本文除了介绍具体的用法外,还会分析背后的逻辑和使用时候的注意事项,力求做到知其然也知其所以然。
Dickensl
2022/06/14
4410
【react】203-十个案例学会 React Hooks
原文地址:https://github.com/happylindz/blog/issues/19
pingan8787
2019/07/23
3.2K0
React Hooks教程之基础篇
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
乐圣
2022/11/19
3K0
React系列-轻松学会Hooks
❗️❗️HOC、Render Props 等基于组件组合的方案,相当于先把要复用的逻辑包装成组件,再利用组件复用机制实现逻辑复用。自然就受限于组件复用,因而出现扩展能力受限、Ref 隔断、Wrapper Hell……等问题
落落落洛克
2021/01/08
4.4K0
React系列-轻松学会Hooks
React hooks 最佳实践【更新中】
导语 随着目前需求更新的节奏越来越快,我们目前更多时候原因使用 function component 来代替类的写法,在 hooks 推出之后,我们也可以完全使用 function component 来代替类的写法;但是俗话说的好,没有什么东西是十全十美的,在本次整理总结 hooks 库的过程中,有体验到 hooks 带来的体验提升,同时也存在对比类生命周期写法中不足的地方。 01 React hooks的思想 首先对于原先的类组件而言,最好的思想是封装,我们使用的constructor、componen
用户1097444
2022/06/29
1.3K0
React hooks 最佳实践【更新中】
浅谈 Hooks
如果你很熟悉 vue 与 react ,兴许你也觉得 vue3.0 抄袭了react,这项react 在不久前发布的新技术,在 vue3.0 中被重新搬上了舞台。也使它重新活跃在了人们的视野中,我技术不深,与大家分享我的见解和猜测。
我不是费圆
2020/10/13
1.9K0
看完这篇,你也能把 React Hooks 玩出花
React v16.7.0-alpha 中第一次引入了 Hooks 的概念,在 v16.8.0 版本被正式发布。React Hooks 在 React 中只是对 React Hook 的概念性的描述,在开发中我们用到的实际功能都应该叫做 React hook。
石燕平
2019/10/14
3.5K0
看完这篇,你也能把 React Hooks 玩出花
React Hook实践指南
在React为什么需要Hook这篇文章中我们探讨了React开发团队为什么要为Function Component添加Hook的原因,在本篇文章中我将会为大家提供一份较为全面的React Hook实践指南,其中包括以下方面的内容:
进击的大葱
2022/08/22
2.6K0
接着上篇讲 react hook
Hook 是一个特殊的函数,使用了 JavaScript 的闭包机制,可以让你在函数组件里“钩入” React state 及生命周期等特性。Hook 不能在 class 组件中使用。这也就是我开篇说的函数式组件一把索的原因
sunseekers
2020/06/03
2.6K0
看完这篇,你也能把 React Hooks 玩出花
React v16.7.0-alpha 中第一次引入了 Hooks 的概念,在 v16.8.0 版本被正式发布。React Hooks 在 React 中只是对 React Hook 的概念性的描述,在开发中我们用到的实际功能都应该叫做 React hook。
Nealyang
2019/09/29
3K0
看完这篇,你也能把 React Hooks 玩出花
95.精读《Function VS Class 组件》
那么 React 中 Function Component 与 Class Component 有何不同?
黄子毅
2022/03/14
5270
95.精读《Function VS Class 组件》
React 16.x 新特性, Suspense, Hooks, Fiber
React 16.6.0 引入了lazy和Suspense。React.lazy函数可以渲染一个动态的import作为一个组件。Suspense悬停组件,它会在内容还在加载的时候先渲染fallback。它们组合就能实现之前主要是使用loadable-components,来异步加载组件,Code-Splitting。
小刀c
2022/08/16
9250
React 16.x 新特性, Suspense, Hooks, Fiber
react hooks 全攻略
React Hooks 是 React 提供的一种功能,允许我们在函数组件中使用状态和其他 React 特性。使用 Hooks 可以简化函数组件中的状态管理和副作用处理。
程序员王天
2023/10/18
6360
React Hooks随记
Hook存储在组件的私有属性中__hooks_list数组中。读取和存储都依赖currentIndex,如果hook的执行顺序改变,currentIndex获取的hook可能是完成错误的。
Clearlove
2021/03/08
9390
react-hooks如何使用?
react-hooks是react16.8以后,react新增的钩子API,目的是增加代码的可复用性,逻辑性,弥补无状态组件没有生命周期,没有数据管理状态state的缺陷。笔者认为,react-hooks思想和初衷,也是把组件,颗粒化,单元化,形成独立的渲染环境,减少渲染次数,优化性能
用户6835371
2021/06/01
3.6K0
react16常见api以及原理剖析
React 与 Vue 有很多相似之处,React 和 Vue 都是非常优秀的框架,它们之间的相似之处多过不同之处,并且它们大部分最棒的功能是相通的:如他们都是 JavaScript 的 UI 框架,专注于创造前端的富应用。不同于早期的 JavaScript 框架“功能齐全”,Reat 与 Vue 只有框架的骨架,其他的功能如路由、状态管理等是框架分离的组件。
前端迷
2019/09/25
1K0
react16常见api以及原理剖析
如何用 Hooks 来实现 React Class Component 写法?
温馨提示:因微信中外链都无法点击,请通过文末的 “阅读原文” 到技术博客中完整查阅版;
JSCON简时空
2020/03/02
2.1K0
React Hooks 性能优化,带你玩转 Hooks
React Hooks 出来很长一段时间了,相信有不少朋友已经深度使用了。无论是react本身还是其生态中,都在摸索着进步。鉴于我使用react的经验,给大家分享一下 React Hooks性能优化可以从哪几个方面入手。至于React Hooks 的使用方式,本文就不做过多的讲解了,可以自行查看https://react.docschina.org/docs/hooks-intro.html
用户1250838
2021/07/09
1.6K0
React Hooks 万字总结
每个 hook 都会有一个 next 指针,hook 对象之间以单向链表的形式相互串联, 同时也能发现 useState 底层依然是 useReducer 再看看更新阶段发生了什么
ConardLi
2021/04/23
9540
React 组件优化方案
如果你知道在什么情况下你的组件不需要更新,你可以在 shouldComponentUpdate 中返回 false 来跳过整个渲染过程。其包括该组件的 render 调用以及之后的操作。该方法会在 重新渲染前 被触发,其默认实现总是返回 true。
多云转晴
2020/02/17
3.3K0
相关推荐
React Hooks 解析(下):进阶
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验