如何在 React 和 Redux 中创建无限滚动? [英] How to create infinite scroll in React and Redux?

查看:69
本文介绍了如何在 React 和 Redux 中创建无限滚动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<块引用>

import React, {useState, useEffect} from 'react';从'react-redux'导入{connect};进口 {获取食谱} 来自'../../store/actions';导入'./BeerRecipes.css';const BeerRecipes = ({recipesData, fetchRecipes}) =>{const [page, setPage] = useState(1);const [食谱,setRecipes] = useState([]);const [loading, setLoading] = useState(true);useEffect(() => {fetchRecipes();}, [])返回 (<div className='beer_recipes_block'><div className='title_wrapper'><h2 className='title'>啤酒食谱</h2>

<div className='beer_recipes'><ul className='beer_recipes_items'>{食谱数据 &&recipesData.recipes &&recipesData.recipes.map(recipe =><li className='beer_recipes_item' id={recipe.id}>{recipe.name}</li>)}

);};const mapStateToProps = state =>{返回 {食谱数据:state.recipes}}const mapDispatchToProps = dispatch =>{返回 {fetchRecipes: () =>调度(fetchRecipes())}}导出默认连接(mapStateToProps,mapDispatchToProps)(BeerRecipes);

这是我想要创建无限滚动的组件,下面是我使用 axios 的 redux-action:

<块引用>

从axios"导入axios;import * as actionTypes from "./actionTypes";导出 const fetchRecipesRequest = () =>{返回 {类型:actionTypes.FETCH_RECIPES_REQUEST}}导出 const fetchRecipesSuccess = 食谱 =>{返回 {类型:actionTypes.FETCH_RECIPES_SUCCESS,有效载荷:配方}}导出 const fetchRecipesFailure = 错误 =>{返回 {类型:actionTypes.FETCH_RECIPES_FAILURE,有效载荷:错误}}export const fetchRecipes = (page) =>{返回(调度)=>{调度(fetchRecipesRequest)公理.get('https://api.punkapi.com/v2/beers?page=1').then(响应 => {const 食谱 = response.data;dispatch(fetchRecipesSuccess(recipes));}).catch(错误=> {const errorMsg = error.message;dispatch(fetchRecipesFailure(errorMsg));})}}

我想创建一个卷轴.我需要首先显示前 10 个元素,然后在每次加载时添加 5 个元素.我总共有 25 个元素,当列表完成后,它应该再次从前五个开始.

解决方案

假设您已经准备好加载下一页的所有内容.您可以使用像 react-in-viewport 这样您就不必处理所有滚动侦听器.

那么你就这样使用它.

从'react-in-viewport'导入handleViewport;const Block = (props: { inViewport: boolean }) =>{const { inViewport, forwardedRef } = props;const 颜色 = inViewport ?'#217ac0':'#ff9800';const text = inViewport ?'在视口中':'不在视口中';返回 (<div className="viewport-block";ref={forwardedRef}><h3>{文本}</h3><div style={{ width: '400px', height: '300px', background: color }}/>

);};const ViewportBlock = handleViewport(Block,/** options: {}, config: {} **/);const 组件 = (props) =>(<div><div style={{ height: '100vh' }}><h2>向下滚动以在视口中制作组件</h2>

<视口块onEnterViewport={() =>console.log('这是内容的底部,让调度加载更多帖子')}onLeaveViewport={() =>console.log('我们可以选择不使用这个.')}/>

))

这里发生的是,它在视口之外创建了一个div",一旦它进入视口(这意味着用户已经滚动到底部),您可以调用一个函数来加载更多帖子.

注意:请记住为您的提取功能添加某种限制.

import React, {useState, useEffect} from 'react';
import {connect} from 'react-redux';

import {
    fetchRecipes
} from '../../store/actions';
import './BeerRecipes.css';

const BeerRecipes = ({recipesData, fetchRecipes}) => {

    const [page, setPage] = useState(1);
    const [recipes, setRecipes] = useState([]);
    const [loading, setLoading] = useState(true);


    useEffect(() => {
        fetchRecipes();
    }, [])

    return (

                <div className='beer_recipes_block'>
                    <div className='title_wrapper'>
                        <h2 className='title'>Beer recipes</h2>
                    </div>
                    <div className='beer_recipes'>
                        <ul className='beer_recipes_items'>
                            {
                                recipesData && recipesData.recipes && recipesData.recipes.map(recipe =>
                                    <li className='beer_recipes_item' id={recipe.id}>{recipe.name}</li>
                                )
                            }
                        </ul>
                    </div>
                </div>

    );
};

const mapStateToProps = state => {
    return {
        recipesData: state.recipes
    }
}

const mapDispatchToProps = dispatch => {
    return {
        fetchRecipes: () => dispatch(fetchRecipes())
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(BeerRecipes);

this is my component where I would like to create infinite scroll and below is my redux-action with axios:

import axios from "axios";
import * as actionTypes from "./actionTypes";

export const fetchRecipesRequest = () => {
    return {
        type: actionTypes.FETCH_RECIPES_REQUEST
    }
}

export const fetchRecipesSuccess = recipes => {
    return {
        type: actionTypes.FETCH_RECIPES_SUCCESS,
        payload: recipes
    }
}

export const fetchRecipesFailure = error => {
    return {
        type: actionTypes.FETCH_RECIPES_FAILURE,
        payload: error
    }
}

export const fetchRecipes = (page) => {
   return (dispatch) => {
       dispatch(fetchRecipesRequest)
        axios
            .get('https://api.punkapi.com/v2/beers?page=1')
            .then(response => {
                const recipes = response.data;
                dispatch(fetchRecipesSuccess(recipes));
            })
            .catch(error => {
                const errorMsg = error.message;
                dispatch(fetchRecipesFailure(errorMsg));
            })
   }
}

I want to create a scroll. I need, firstly, to display first 10 elements and then to add 5 elements with every loading. I have 25 elements altogether and when the list is done it should start from the first five again.

解决方案

Assuming you already have everything ready to load your next page. You can probably simplify the entire process by using a package like react-in-viewport so you don't have to deal with all the scroll listeners.

then you use it like this way.

import handleViewport from 'react-in-viewport';
 
const Block = (props: { inViewport: boolean }) => {
  const { inViewport, forwardedRef } = props;
  const color = inViewport ? '#217ac0' : '#ff9800';
  const text = inViewport ? 'In viewport' : 'Not in viewport';
  return (
    <div className="viewport-block" ref={forwardedRef}>
      <h3>{ text }</h3>
      <div style={{ width: '400px', height: '300px', background: color }} />
    </div>
  );
};
 
const ViewportBlock = handleViewport(Block, /** options: {}, config: {} **/);
 
const Component = (props) => (
  <div>
    <div style={{ height: '100vh' }}>
      <h2>Scroll down to make component in viewport</h2>
    </div>
    <ViewportBlock 
         onEnterViewport={() => console.log('This is the bottom of the content, lets dispatch to load more post ')} 
         onLeaveViewport={() => console.log('We can choose not to use this.')} />
  </div>
))

What happen here is, it creates a 'div' which is outside the viewport, once it comes into the view port ( it means user already scrolled to the bottom ), you can call a function to load more post.

To Note: Remember to add some kind of throttle to your fetch function.

这篇关于如何在 React 和 Redux 中创建无限滚动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆