React Hooks简单业务场景实战(非源码解读)

ldld 2019-06-22 原文

React Hooks简单业务场景实战(非源码解读)

 前言

React Hooks 是React 16.7.0-alpha 版本推出的新特性。从 16.8.0 开始,React更稳定的支持了这一新特性。

它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

注意:React 16.8.0 是第一个支持 Hook 的版本。升级时,请注意更新所有的 package,包括 React DOM。React Native 将在下一个稳定版本中支持 Hook。

如果说promise是JavaScript异步的终极解决方案,那么React Hooks从某种意义上来说,也是react状态管理的终极解决方案。

为什么用 React Hooks?与其他状态管理方案有什么区别?

在react hooks,react态管理方案主要有如下2种:

这两种状态解决方案其实已经很不错,可以满足绝大多数状态共享的业务场景。 当然,像FB这样优秀的团队优秀的人总喜欢钻研,不断优化。认为这两种状态解决方案嵌套太多,很多业务逻辑可以抽象出来。不仅仅是共享状态就完事了,还得共享出处理逻辑。为了减少不必要的组件嵌套写法,实现更扁平、颗粒化的状态 + 逻辑的复用,于是便推出了 React Hooks。

关于react hooks,具体可以多看看React Hooks官方文档,理解会更深。

业务实战1:实现一个简单的显示隐藏弹出框

1、基于 render-props实现:

// 将父组建的 on状态 和toggle 事件,共享给嵌套下的子组件
function App() {
 return (
   <Toggle initial={false}>
     {({ on, toggle }) => (
       <Button type="primary" onClick={toggle}> Open Modal </Button>
       <Modal visible={on} onOk={toggle} onCancel={toggle} />
     )}
   </Toggle>
 )
}

2、用react hooks实现

import React, { useState } from 'react';

function Example() {
  // 声明一个新的叫做 “visible” 的 state 变量
  const [visible, setVisible] = useState(false);

  return (
    <div>
      <Modal onClick={() => setVisible(!visible)}>
        Click me
      </Modal>
    </div>
  );
}

业务实战2: 接收传入props后立马更新自有的State状态(received passed props and updated)

function Avatar(props) {
 const [user, setUser] = React.useState({...props.user}); // 这里仅仅是给了一个初始值,仅第一次渲染的时候生效,后续都不会再更新了。

 // 用useEffect,第二个参数传入一个数组字段props.user,
 // 表示每次只要传入的props.user有变化,那么就触发setUser这个操作更新状态。
 React.useEffect(() => {
     setUser(props.user);
 }, [props.user])

 return user.avatar ? 
        (<img src={user.avatar}/>)
       : (<p>Loading...</p>);
}

由上述例子可以看到,我们用到了useEffect这个hooks。

Effect Hook 可以让你在函数组件中执行副作用操作

什么叫副作用呢? 数据获取,设置订阅以及手动更改 React 组件中的 DOM 都属于副作用。

如果实在理解不了副作用,你可以理解为,在我们在写传统的react class组件里面的生命周期钩子函数componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合中处理的相关逻辑,就是副作用。

也就是说,任何你想在页面首次加载完(componentDidMount),后续每次更新完(componentDidUpdate),亦或者是组件卸载前(componentWillUnmount),这三个勾子中加入你自己的逻辑处理,就得用到useEffect

业务实战3:显示后,倒计时自动隐藏(与setInterval结合)

业务场景具体如下:实现一个倒计时30秒,每秒钟减1,然后倒计时完毕这个组件自动隐藏。

function App() {
  const [count, setCount] = useState(30);
  useEffect(() => {
    setInterval(() => {
      setCount(count - 1);
    }, 1000);
  });
  return <div className="App">{count}</div>;
}

看看上述的写法,自己运行一下就只知道了,肯定是大错特错的。 最基本的,setInterval这个删除定时器都没有做相关处理。 其次,每次都会生成不同都setInterval实例。那么如何加以控制呢?

来看看正确都写法,这里要用到useRef这种类型都hooks了。


function App(props){
    const [visible,setVisible] = useState(false);// 初始化值为false,隐藏
    const [count,setCount] = useState(0); // 倒计时字段,初始值为0
    // 明确定时器要做什么:我们这里是每秒 -1,小于等于0的时候就自动给隐藏
    // 同时,本此的跟新跟下次的渲染更新要共享状态,记住上次更新这个count减到哪里了
    // 基于上述问题,我们可以使用如下方案:
    // 声明一个useRef对象,初始化为null
    const intervalCb = useRef(null); 
    useEffect(()=>{
      // useRef 对象有一个current属性,可以给它赋值为一个函数
      intervalCb.current = () => { 
      if(count  <= 0){
        setVisible(false);
      }else{
        setCount(count - 1);
      }    
    };   
    })
    
    // 在componentDidMount中设置一个定时器
    useEffect(()=>{
        function itvFn(){
            // 在此前,定时器的回调函数已经声明,这里可以直接调用
            intervalCb.current(); 
        }
        const itvId = window.setInterval(itvFn,1000);
        // return 一个回调函数,表示清除处理
        return () => window.clearInterval(itvId);
    },[]) // 传入要监听的对象,空数组表示只监听一次,相当于didMounted
}

return (<div className={visible}>
        {count}
    </div>)
}

关于useRef 更多的请看useRef官方文档

业务实战4: 自定义hooks

基于上述setInterval的业务功能实现,我们简单的来写一个自定义的hooks

export default function useInterval(callback) {
 const savedCallback = useRef();

 useEffect(() => {
   savedCallback.current = callback;
 });

 useEffect(() => {
   function tick() {
     savedCallback.current();
   }

   let id = setInterval(tick, 1000);
   return () => clearInterval(id);
 }, []);
}

然后在你需要用到的地方引入:

import useInterval from 'xx/self_hooks';

function App(){
   useInterval(()=>{
       // ... 跟useEffect写法类似,目前只支持传入一个function类型的参数,如果要接收多个参数,那么在自定义hooks那里去自行处理一下。
   })
}

关于自定义hooks,更多请查看自定义hooks

暂结

关于react hooks 简单的使用,此篇就暂时写到这里,当然,复杂一点的,可以使用useReducer、useContext和useEffect代替Redux方案。后续我们应该单独来研究这块。 回顾一下,如何才能说我们会用react hooks 呢?

  • 第一、明白概念,干什么用的,解决哪些痛点?
  • 第二、useEffect传入几个参数?分表表示声明?useRef作用是什么?这些可以解决我们基本的业务需求。
  • 第三、useReducer、useContext 怎么替换 redux?
  • 读源码,搞清楚为什么useEffect不能卸载if嵌套中等之类的问题?

今天先把问题抛出,后续按照这个,循序渐进的学习掌握react hooks。

发表于 2019-06-22 18:34 liudddd 阅读() 评论() 编辑 收藏

 

版权声明:本文为ldld原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/ldld/p/11069906.html

React Hooks简单业务场景实战(非源码解读)的更多相关文章

  1. React优化

    这里主要分析在函数式react中的优化,类组件有生命周期函数定义较明确 React的核心特征之一是单向数据流( […]...

  2. 使用 antd 的 form 组件来自定义提交的数据格式

    最近使用antd UI 的表单提交数据,数据里面有的是数组,有的是对象。提交的时候还要去校验参数,让人非常头疼 […]...

  3. JSX语法详解

    JSX语法详解 一、基础1、JSX是什么JSX是一种像下面这样的语法: const element = < […]...

  4. SPA 路由三部曲之核心原理

    为了配合单页面 Web 应用快速发展的节奏,近几年,各类前端组件化技术栈层出不穷。通过不断的版本迭代 Reac […]...

  5. 【bird-front】全自动数据表格组件bird-grid

    bird-grid是bird-front前端框架中实现的全自动数据表格组件。组件内部处理数据加载、分页、排序、 […]...

  6. Vue与React两个框架的区别对比

    简单介绍 React–Facebook创建的JavaScript UI框架。它支撑着包括Insta […]...

  7. React 进阶之路(六)

    之前的文章我们介绍了 React 表单事件 键盘事件 事件对象以及 React中 的 ref 获取 dom 节 […]...

  8. React + TypeScript 实现泛型组件

    泛型类型 TypeScript 中,类型(interface, type)是可以声明成泛型的,这很常见。 in […]...

随机推荐

  1. 温故知新-分布式锁的实现原理和存在的问题

    目录 摘要 锁 分布式锁的特点 分布式锁的实现方式 MySql zookeeper 存在问题 redis re […]...

  2. Python 二维矩阵 行列转置的多种实现方法

    最近在读写 MySQL 数据的过程中,碰到了需要处理 二维矩阵数据 行列转置 的问题,比如将: [[1, 2, […]...

  3. [book]程序员修炼之道 – 张大大123

    [book]程序员修炼之道 看了dearbook上的介绍就决定必买: 内容简介:  本书于2004年3月18日 […]...

  4. oracle如何设置最大连接数

    查看session:   select * from v$session where username is […]...

  5. Docker笔记(一):什么是Docker

    原文地址: http://blog.jboost.cn/2019/07/13/docker-1.html  1 […]...

  6. Docker基础命令

    Docker基础命令操作 1)拉取一个镜像 1 [root@zabbix-c48 ~]# docker pul […]...

  7. Quartus ii调试技巧_01

     前几天李主任跟我分享了一些特别好用的调试技巧: 1)System Sources and Probes Ed […]...

  8. 性能测试的指标有哪些? – 测试达人2016

    性能测试的指标有哪些? 2016-11-03 22:53  测试达人2016  阅读(915)  评论(0)  […]...

展开目录

目录导航