一次完整的react hooks实践

栏目: 服务器 · 发布时间: 6年前

内容简介:本文首发于公众号:符合预期的CoyPanReact在16.8版本正式发布了Hooks。关注了很久,最近正好有一个小需求,赶紧来试一下。

写在前面

一次完整的react hooks实践

本文首发于公众号:符合预期的CoyPan

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/hook...

本次需求其实就两个逻辑: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/hook...

写在后面

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

一次完整的react hooks实践


以上所述就是小编给大家介绍的《一次完整的react hooks实践》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

HTML5与CSS3权威指南(上册) (第3版)

HTML5与CSS3权威指南(上册) (第3版)

陆凌牛 / 机械工业出版社 / 2015-9-1 / CNY 89.00

本书是HTML 5与CSS 3领域公认的标杆之作,被读者誉为“系统学习HTML 5与CSS 3的最佳著作”和“Web前端工程师案头必备图书之_”。 前两版累计印刷超过15次,网络书店评论超过8000条,98%以上的评论都是五星级的好评。不仅是HTML 5与CSS 3图书领域当之无愧的领头羊,而且在整个原创计算机图书领域是佼佼者。 第3版首先从技术的角度根据最新的HTML 5和CSS 3......一起来看看 《HTML5与CSS3权威指南(上册) (第3版)》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具