前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React-Hook实现数据获取管理和滚动获取

React-Hook实现数据获取管理和滚动获取

原创
作者头像
我已经洗完澡了
修改2019-10-14 17:15:28
2.2K0
修改2019-10-14 17:15:28
举报
文章被收录于专栏:React App && Python Flask

layout: post

title: React-Hook实现数据获取

date: 2019-10-05

author: 霁

header-img:

catalog: true

categories:

  • 学习
  • React tags:
  • React

前言

本文发布与个人博客

为了实现一个获取数据并进行管理。

为了实现在函数式组件里下拉获取数据想尽方法。最后使用

react-infinite-scroller.还是在类里面写好了。

自定义异步Hook

封装一个自定义Hook

代码语言:txt
复制
import {useEffect,useState,useReducer} from 'react';

import {Axios_get} from '../api/server';
import { listReducer } from './reducers/listReducer';

import { requestList, receiveList, receiveError,noMore } from './actions/listActions';


function useListHook(initialUrl) {

    const [url,setUrl] = useState(initialUrl);

    const [listState,listDispatch] = useReducer(listReducer,{
        isLoading:false,
        isError:false,
        hasMore:true,
        message:'',
        dataSource:[],
    });

    useEffect(() => {
        let didCancel = false;
        Axios_get(url,(rs)=>{
            listDispatch(requestList());
            console.log(rs)
            if(!rs.data){
                if(!didCancel){
                    listDispatch(receiveError(rs));
                }
            }
            if(rs.data.list.length===0){
                listDispatch(noMore(rs));
            }
            if(rs.status!==0){
                if(!didCancel){
                    listDispatch(receiveList(rs.data))
                }
            }else{
                if(!didCancel){
                    listDispatch(receiveError(rs));
                }
            }
        });
        return () => {
            didCancel = true;
        };
    },[url])

    const handlerSetUrl = (url)=>setUrl(url);

    return [listState,handlerSetUrl]
}
export {useListHook}

本来是想要暴露出的handlerSetUrl 通过改变url进行下一页的获取,但是老是出现错误。

唉,还有待理解react。

上面这个把 reducer 和action 写在另外的地方

IntersectionObserver

看了一些方案:

本来的希望是在需要list数据的组件底部,放入一个div 以指示已经到达底部,需要改变url获取新数据了,但是出现了错误。

说说这个IntersectionObserver 吧。

这个是一个新的web api 。我们可以去查看文档。Observert

做要用于监听一个元素是否在可视范围。以及出现在可视范围的回调函数,和离开可视范围的回调。

阮一峰老师也有介绍

可以利用这个来实现一个虚拟无限列表吧。

代码语言:txt
复制
import React,{useState,useEffect,useRef} from 'react'

export default function Observe({callback}) {

    const obRef = useRef();
    const [observer, setObserver] = useState(null);

    useEffect(() => {
        const initiateScrollObserver = (_dom) => {
            const io = new IntersectionObserver(callback);
            if (_dom) {
                io.observe(_dom);
            }
            setObserver(io);
        }

        initiateScrollObserver(obRef.current);

        const resetObservation = () => {
            observer && observer.disconnect();
        }
        return () => {
            resetObservation();
        };
    }, [observer,callback])

    return (
        <div ref={obRef} hidden></div>
    )
}

企图通过当这个div出现在视口的时候调用更改组件的url来获取新的数据,但是出现了更改setate过深?的错误。

。。。。

最后使用插件。

代码语言:txt
复制
import React, { Component } from 'react';

import InfiniteScroll from 'react-infinite-scroller';

import ListItem from './ListItem';
import Spin from './Spin';
import Error from './Error';
import { Axios_get } from '../api/server';


export default class List extends Component {

    constructor(props){
        super(props);
        this.state = {
            isLoading:false,
            isError:false,
            hasMore:true,
            message:'',
            dataSource:[],
            page:1,
            pageSize:5,
        }
    }
    componentDidMount() {
        this.handleLoad();
    }

    handleLoad = ()=>{
        let {page,pageSize,dataSource} = this.state;
        this.setState({
            isLoading:true,
        })
        let url = `/movies/${page}/${pageSize}`;
        Axios_get(url,(rs)=>{
            console.log(rs)
            if(!rs.data){
                this.setState({
                    isLoading:false,
                    isError:true,
                    message:rs.toString()
                })
            }else{
                const {list,has_next} = rs.data;
                if(!has_next){
                    this.setState({
                        isLoading:false,
                        hasMore:false,
                        message:'No More',
                    })
                }
                if(rs.status===200 && has_next){
                    dataSource = dataSource.concat(list);
                    page = ++page;
                    this.setState({
                        isLoading:false,
                        hasMore:true,
                        dataSource,
                        page,
                    })
                }
            }
        })
    }


    render() {
        const {dataSource,isError,isLoading,hasMore,message} = this.state;
        const items = dataSource.map(item=>
            <ListItem key={item.id} item={item}/>
        )
        return (
        !isError?<InfiniteScroll
        threshold={0}
        className="rush-list"
        initialLoad={false} 
        pageStart={0}
        loadMore={this.handleLoad}
        hasMore={!isLoading && hasMore}>
        {items}
        {isLoading && hasMore&&(
            <div className="loading-container">
                <Spin />
            </div>
        )}
    </InfiniteScroll>:<Error message={message}/>
    )}
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 自定义异步Hook
  • IntersectionObserver
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档