layout: post
title: React-Hook实现数据获取
date: 2019-10-05
author: 霁
header-img:
catalog: true
categories:
本文发布与个人博客
为了实现一个获取数据并进行管理。
为了实现在函数式组件里下拉获取数据想尽方法。最后使用
react-infinite-scroller.还是在类里面写好了。
封装一个自定义Hook
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 写在另外的地方
看了一些方案:
本来的希望是在需要list数据的组件底部,放入一个div 以指示已经到达底部,需要改变url获取新数据了,但是出现了错误。
说说这个IntersectionObserver 吧。
这个是一个新的web api 。我们可以去查看文档。Observert
做要用于监听一个元素是否在可视范围。以及出现在可视范围的回调函数,和离开可视范围的回调。
可以利用这个来实现一个虚拟无限列表吧。
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过深?的错误。
。。。。
最后使用插件。
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 删除。