记录一次完整的react hooks实践


Posted in Javascript onMarch 11, 2019

写在前面

记录一次完整的react hooks实践

React在16.8版本正式发布了Hooks。关注了很久,最近正好有一个小需求,赶紧来试一下。

需求描述

需求很简单,部门内部的一个数据查询小工具。大致长成下面这样:

记录一次完整的react hooks实践

用户首次访问页面,会拉取数据展示。输入筛选条件,点击查询后,会再次拉取数据在前端展示。

需求实现

使用React Class Component的写法

如果使用以前的class写法,简单写一下,代码可能大概长成下面这样:

import React from 'react';
import { Tabs, Input, RangeTime, Button, Table } from './components';

class App extends React.Component {
  ...
  state = {
    type: [],
    id: '',
    title: '',
    date: [],
    dataList: []
  }
  componentDidMount() {
    this.fetchData();
  }
  render() {
    <Tabs value={this.state.type} onChange={this.handleTypeChange}/>
    <Input value={this.state.id} label="ID" onChange={this.handleIdChange}/>
    <Input value={this.state.id} label="标题" onChange={this.handleTitleChange}/>
    <RangeTime value={this.state.date} onChange={this.handleRangeTimeChange}/>
    <Button onClick={this.handleQueryBtnClick}>查询</Button>
    <Table dataList={this.state.dataList} />
  }
  
  fetchData() {
    ...
    this.setState({
      dataList
    });
  }

  handleTypeChange() {
    ...
    this.setState({
      type,
    });
  }
  
  handleIdChange() {
    ...
    this.setState({
      id,
    });
  }

  handleTitleChange() {
    ...
    this.setState({
      title,
    });
  }

  handleRangeTimeChange() {
    ...
    this.setState({
      date,
    });
  }

  handleQueryBtnClick() {
    ...
  }
  ...
}

使用React Hooks的写法

关于React hooks的相关内容,这里就不赘述了。可以直接查看react官方文档,写得非常好。

https://reactjs.org/docs/hooks-intro.html

本次需求其实就两个逻辑:1、输入筛选项 。2、查询数据

主页面一个hooks,处理筛选项以及数据展示。数据请求逻辑单独弄一个hooks。

主页面hooks:

import React, { useState, useEffect} from 'react';
import { Tabs, Input, RangeTime, Button, Table } from './components';

const App = () => {
  // 数据类型
  const tabs = [{ key: 1, value: '类型1' }, { key: 0, value: '类型2' }];
  const [tab, setTab] = useState(1);
  // 数据ID
  const [dataId, setDataid] = useState('');
  // 标题
  const [title, setTitle] = useState('');
  // 时间区间, 默认为至今一周时间
  const now = Date.now();
  const [timeRange, setTimeRange] = useState([now - 1000 * 60 * 60 * 24 * 7, now]);
  // 数据列表
  const [dataList, setDataList] = useState([]);

  // 点击搜索按钮
  function handleBtnClick() {
    // 请求数据
    ...
  }

  return <section className="app">
    <Title title="数据查询" />
    <Tabs label="类型" tabs={tabs} tab={tab} onChange={setTab} />
    <Input value={dataId} placeholder="请输入数据ID" onChange={setDataid}>ID</Input>
    <Input value={title} placeholder="请输入数据标题" onChange={setTitle}>标题</Input>
    <TimeRange label="数据时间" value={timeRange} onChange={handleTimeChange}/>
    <article className="btn-container">
      <Button type="primary" onClick={handleBtnClick}>
        查询          
      </Button>
    </article>
    <Table dataList={dataList}></Table>
  </section>
};

上面的代码,完成了筛选项的处理逻辑。下面来实现负责数据请求的hooks.

数据请求hooks:

import React, { useState, useEffect } from 'react';
import jsonp from '../tools/jsonp';


function MyFecth(url) {
  // 是否正在请求中
  const [isLoading, setIsLoanding] = useState(false);
  // 请求参数
  const [queryParams, setQueryParams] = useState(null);
  // 请求结果
  const [data, setData] = useState(null);

  // 向接口发起请求
  const fetchData = async () => {
    if(queryParams === null) {
      return;
    }
    setIsLoanding(true);
    const res = await jsonp({
      url: url,
      data: queryParams
    });
    setData(res);
    setIsLoanding(false);
  }

  // 只要queryParams改变,就发起请求
  useEffect(()=> {
    fetchData();
  }, [queryParams]);


  // 供外部调用
  const doGet = (params) => {
    setQueryParams(params);
  }

  return {
    isLoading,
    data,
    doGet
  }
}

export default MyFecth;

在主页面中,引用数据请求hooks:

import React, { useState, useEffect} from 'react';
import { Tabs, Input, RangeTime, Button, Table } from './components';
import MyFecth from './MyFetch';

const App = () => {

  // ①使用数据请求hooks
  const { isLoading, data, doGet } = MyFecth('http://xxx');
  
  // 数据类型
  const tabs = [{ key: 1, value: '类型1' }, { key: 0, value: '类型2' }];
  const [tab, setTab] = useState(1);
  // 数据ID
  const [dataId, setDataid] = useState('');
  // 标题
  const [title, setTitle] = useState('');
  // 时间区间, 默认为至今一周时间
  const now = Date.now();
  const [timeRange, setTimeRange] = useState([now - 1000 * 60 * 60 * 24 * 7, now]);
  // 数据列表
  const [dataList, setDataList] = useState([]);
  
  
  
  // 点击搜索按钮
  function handleBtnClick() {
    // ②点击按钮后请求数据
    const params = {};
    title && (params.title = title);
    dataId && (params.dataId = dataId);
    params.startTime = String(timeRange[0]);
    params.endTime = String(timeRange[1]);
    doGet(params);
  }
  
  // ③data改变后,重新渲染列表。
  // 这里相当于 componentDidUpdate。当data发生改变时,重新渲染页面
  useEffect(() => {
    setDataList(data);
  }, [data]);
  
  // ④首次进入页面时,无任何筛选项。拉取数据,渲染页面。
  // useEffect第二个参数为一个空数组,相当于在 componentDidMount 时执行该「副作用」
  useEffect(() => {
    doGet({});
  }, []);


  return <section className="app">
    <Title title="数据查询" />
    <Tabs label="类型" tabs={tabs} tab={tab} onChange={setTab} />
    <Input value={dataId} placeholder="请输入数据ID" onChange={setDataid}>ID</Input>
    <Input value={title} placeholder="请输入数据标题" onChange={setTitle}>标题</Input>
    <TimeRange label="数据时间" value={timeRange} onChange={handleTimeChange}/>
    <article className="btn-container">
      <Button type="primary" isLoading={isLoading} onClick={handleBtnClick}>
        查询          
      </Button>
    </article>
    <Table dataList={dataList}></Table>
  </section>
};

关于React Hooks的一些思考

使用hooks写完这个需求,最直观的感受就是,代码写起来很爽。不需要像以前那样写很多的setState。其次就是

hooks的api设计得很优秀,一个useState的就能将【状态】和【变更状态的逻辑】两两配对。React的基本思想就是【数据到视图的映射】,在hooks中,使用useEffect来表明其中的【副作用】,感觉react官方也倾向于不区分componentDidMount和componentDidUpdate。

从api设计就能看出,hooks提倡组件状态细粒度地拆分。在一个hooks组件中,可能包含很多的状态,如果用户的某些操作,需要同时修改两个状态,那么我需要分别调用这两个状态的修改逻辑,这样会导致组件被重新render两次。而在使用class写法的组件中,只需要一次setState就好。这样看来,hooks中render两次的操作,可能会带来些许的性能问题 ? 这就要求我们在设计组件结构和state时,多斟酌,多抽象。

关于hooks的一些FAQ,官方也有很棒的文档:https://reactjs.org/docs/hooks-faq.html

写在后面

本文通过工作中的一个小需求,完成了一次react hooks的实践,不过上述代码依然有很多需要优化的地方。这次实践让我最直观的接触了react hooks,也帮助自己进一步理解了react团队的一些思想。符合预期。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 学习之旅 (1)
Feb 05 Javascript
深入讲解AngularJS中的自定义指令的使用
Jun 18 Javascript
Webpack 实现 Node.js 代码热替换
Oct 22 Javascript
第一次接触神奇的Bootstrap表单
Jul 27 Javascript
利用Plupload.js解决大文件上传问题, 带进度条和背景遮罩层
Mar 15 Javascript
设置cookie指定时间失效(实例代码)
May 28 Javascript
Vue中计算属性computed的示例解读
Jul 26 Javascript
原生javascript实现的全屏滚动功能示例
Sep 19 Javascript
jQuery实现根据身份证号获取生日、年龄、性别等信息的方法
Jan 09 jQuery
three.js利用卷积法如何实现物体描边效果
Nov 27 Javascript
Node.js文本文件BOM头的去除方法
Nov 22 Javascript
vue实现图片裁剪后上传
Dec 16 Vue.js
es6数值的扩展方法
Mar 11 #Javascript
Vue实现一个图片懒加载插件
Mar 11 #Javascript
使用Jenkins部署React项目的方法步骤
Mar 11 #Javascript
vue基础之v-bind属性、class和style用法分析
Mar 11 #Javascript
配置eslint规范项目代码风格
Mar 11 #Javascript
vue基础之事件简写、事件对象、冒泡、默认行为、键盘事件实例分析
Mar 11 #Javascript
vue基础之事件v-onclick=&quot;函数&quot;用法示例
Mar 11 #Javascript
You might like
javascript while语句和do while语句的区别分析
2007/12/08 Javascript
Jquery 获取checkbox的checked问题
2011/11/16 Javascript
javaScript让文本框内的最后一个文字的后面获得焦点实现代码
2013/01/06 Javascript
jquery实现excel导出的方法
2013/04/04 Javascript
你必须知道的JavaScript 变量命名规则详解
2013/05/07 Javascript
javascript中的self和this用法小结
2014/02/08 Javascript
jquery 构造函数在表单提交过程中修改数据
2015/05/25 Javascript
vue.js绑定class和style样式(6)
2016/12/09 Javascript
nodejs nedb 封装库与使用方法示例
2020/02/06 NodeJs
小谈angular ng deploy的实现
2020/04/07 Javascript
Vue通过provide inject实现组件通信
2020/09/03 Javascript
[49:05]Newbee vs TNC 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
python 图片验证码代码
2008/12/07 Python
python如何去除字符串中不想要的字符
2020/07/05 Python
Python3爬虫爬取英雄联盟高清桌面壁纸功能示例【基于Scrapy框架】
2018/12/05 Python
python 实现分页显示从es中获取的数据方法
2018/12/26 Python
python设置环境变量的原因和方法
2019/06/24 Python
python文件和文件夹复制函数
2020/02/07 Python
python实现门限回归方式
2020/02/29 Python
Python实现仿射密码的思路详解
2020/04/23 Python
基于FME使用Python过程图解
2020/05/13 Python
详解python定时简单爬取网页新闻存入数据库并发送邮件
2020/11/27 Python
python statsmodel的使用
2020/12/21 Python
CSS3中新增的对文本和字体的设置
2020/02/03 HTML / CSS
viagogo法国票务平台:演唱会、体育比赛、戏剧门票
2017/03/27 全球购物
意大利宠物用品购物网站:Bauzaar
2018/09/15 全球购物
中文专业毕业生自荐信
2014/05/24 职场文书
物业总经理助理岗位职责
2014/06/29 职场文书
观看《周恩来的四个昼夜》思想汇报
2014/09/12 职场文书
先进工作者事迹材料
2014/12/23 职场文书
晚会开幕词
2015/01/28 职场文书
汉语拼音教学反思
2016/02/22 职场文书
大学生饮品店创业计划书范文
2019/07/10 职场文书
大学生奖学金获奖感言(范文)
2019/08/15 职场文书
详细了解MVC+proxy
2021/07/09 Java/Android
vue配置型表格基于el-table拓展之table-plus组件
2022/04/12 Vue.js