Giter Site home page Giter Site logo

ankeetmaini / react-infinite-scroll-component Goto Github PK

View Code? Open in Web Editor NEW
2.8K 2.8K 315.0 2.56 MB

An awesome Infinite Scroll component in react.

Home Page: https://react-infinite-scroll-component.netlify.com/

License: MIT License

JavaScript 23.81% TypeScript 76.19%
component infinite-lists infinite-scroll npm-package react

react-infinite-scroll-component's Introduction

react-infinite-scroll-component npm npm

All Contributors

A component to make all your infinite scrolling woes go away with just 4.15 kB! Pull Down to Refresh feature added. An infinite-scroll that actually works and super-simple to integrate!

Install

  npm install --save react-infinite-scroll-component

  or

  yarn add react-infinite-scroll-component

  // in code ES6
  import InfiniteScroll from 'react-infinite-scroll-component';
  // or commonjs
  var InfiniteScroll = require('react-infinite-scroll-component');

Using

<InfiniteScroll
  dataLength={items.length} //This is important field to render the next data
  next={fetchData}
  hasMore={true}
  loader={<h4>Loading...</h4>}
  endMessage={
    <p style={{ textAlign: 'center' }}>
      <b>Yay! You have seen it all</b>
    </p>
  }
  // below props only if you need pull down functionality
  refreshFunction={this.refresh}
  pullDownToRefresh
  pullDownToRefreshThreshold={50}
  pullDownToRefreshContent={
    <h3 style={{ textAlign: 'center' }}>&#8595; Pull down to refresh</h3>
  }
  releaseToRefreshContent={
    <h3 style={{ textAlign: 'center' }}>&#8593; Release to refresh</h3>
  }
>
  {items}
</InfiniteScroll>

Using scroll on top

<div
  id="scrollableDiv"
  style={{
    height: 300,
    overflow: 'auto',
    display: 'flex',
    flexDirection: 'column-reverse',
  }}
>
  {/*Put the scroll bar always on the bottom*/}
  <InfiniteScroll
    dataLength={this.state.items.length}
    next={this.fetchMoreData}
    style={{ display: 'flex', flexDirection: 'column-reverse' }} //To put endMessage and loader to the top.
    inverse={true} //
    hasMore={true}
    loader={<h4>Loading...</h4>}
    scrollableTarget="scrollableDiv"
  >
    {this.state.items.map((_, index) => (
      <div style={style} key={index}>
        div - #{index}
      </div>
    ))}
  </InfiniteScroll>
</div>

The InfiniteScroll component can be used in three ways.

  • Specify a value for the height prop if you want your scrollable content to have a specific height, providing scrollbars for scrolling your content and fetching more data.
  • If your scrollable content is being rendered within a parent element that is already providing overflow scrollbars, you can set the scrollableTarget prop to reference the DOM element and use it's scrollbars for fetching more data.
  • Without setting either the height or scrollableTarget props, the scroll will happen at document.body like Facebook's timeline scroll.

docs version wise

3.0.2

live examples

  • infinite scroll (never ending) example using react (body/window scroll)
    • Edit yk7637p62z
  • infinte scroll till 500 elements (body/window scroll)
    • Edit 439v8rmqm0
  • infinite scroll in an element (div of height 400px)
    • Edit w3w89k7x8
  • infinite scroll with scrollableTarget (a parent element which is scrollable)
    • Edit r7rp40n0zm

props

name type description
next function a function which must be called after reaching the bottom. It must trigger some sort of action which fetches the next data. The data is passed as children to the InfiniteScroll component and the data should contain previous items too. e.g. Initial data = [1, 2, 3] and then next load of data should be [1, 2, 3, 4, 5, 6].
hasMore boolean it tells the InfiniteScroll component on whether to call next function on reaching the bottom and shows an endMessage to the user
children node (list) the data items which you need to scroll.
dataLength number set the length of the data.This will unlock the subsequent calls to next.
loader node you can send a loader component to show while the component waits for the next load of data. e.g. <h3>Loading...</h3> or any fancy loader element
scrollThreshold number | string A threshold value defining when InfiniteScroll will call next. Default value is 0.8. It means the next will be called when user comes below 80% of the total height. If you pass threshold in pixels (scrollThreshold="200px"), next will be called once you scroll at least (100% - scrollThreshold) pixels down.
onScroll function a function that will listen to the scroll event on the scrolling container. Note that the scroll event is throttled, so you may not receive as many events as you would expect.
endMessage node this message is shown to the user when he has seen all the records which means he's at the bottom and hasMore is false
className string add any custom class you want
style object any style which you want to override
height number optional, give only if you want to have a fixed height scrolling content
scrollableTarget node or string optional, reference to a (parent) DOM element that is already providing overflow scrollbars to the InfiniteScroll component. You should provide the id of the DOM node preferably.
hasChildren bool children is by default assumed to be of type array and it's length is used to determine if loader needs to be shown or not, if your children is not an array, specify this prop to tell if your items are 0 or more.
pullDownToRefresh bool to enable Pull Down to Refresh feature
pullDownToRefreshContent node any JSX that you want to show the user, default={<h3>Pull down to refresh</h3>}
releaseToRefreshContent node any JSX that you want to show the user, default={<h3>Release to refresh</h3>}
pullDownToRefreshThreshold number minimum distance the user needs to pull down to trigger the refresh, default=100px , a lower value may be needed to trigger the refresh depending your users browser.
refreshFunction function this function will be called, it should return the fresh data that you want to show the user
initialScrollY number set a scroll y position for the component to render with.
inverse bool set infinite scroll on top

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Ankeet Maini

πŸ’¬ πŸ“– πŸ’» πŸ‘€ 🚧

Darsh Shah

πŸš‡

This project follows the all-contributors specification. Contributions of any kind are welcome!

LICENSE

MIT

react-infinite-scroll-component's People

Contributors

aladouagi avatar allcontributors[bot] avatar ankeetmaini avatar babycannotsay avatar cescoferraro avatar daggmano avatar danielcaldas avatar danielsogl avatar dependabot[bot] avatar echoulen avatar ethaizone avatar fooki avatar harrybabu avatar iamdarshshah avatar ipanasenko avatar ishaan28malik avatar kikobeats avatar leonh avatar meberem avatar nero120 avatar newbie012 avatar nitkuk avatar osmarpb97 avatar rajatsan avatar rgoyal1405 avatar squgeim avatar thebearso avatar vladik7244 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-infinite-scroll-component's Issues

Want to hide scroll bars

I'm using your package on a large touchscreen and I'd rather not see scroll bars but I don't see a way to override your overflow: auto style

How to add a custom class?

Hi,

I would like to add some custom class instead "infinite-scroll-component". How can I do this?

Thanks

Set scrollable container?

Hi @ankeetmaini, I'm using your component for a plugin I'm building and I can say that so far it's much better than most of the other React infinite scrollers I've tried so thank you!

My only issue is that the application that my plugin will be displayed in never scrolls on document.body, it uses a scrollable container div for displaying content inside. Because of this, if I don't use the height prop, next never triggers. If I do use height then everything works except that the user now has two sets of scroll bars, one on the applications scrollable container and one on the infinite scroll component. This is a bit of an ugly experience so I was wondering if there's any way of setting the target scrollable container to a particular element? That way next could be trigger when then user scrolls to the bottom of the application's scrollable container. Hope that makes sense!

Add pull down to refresh as well?

Great library that actually works! I realized no other React.js infinite scroll components support both pull down to refresh and pull up to load more, if this can be implemented as well, it could be make this library a killer!

does not load the first page if not scrolling down

the next callback seems to be called only after a scroll down event. if the page isn't full and I cannot scroll down to the bottom (cause I already reached it), then the loader is displayed, but the next callback doesn't get called. this is obvious when you start the component with no children.

Loader remains visible with endMessage?

The Loader prop remains visible even after passing false to hasMore and injecting new children.

Below you can see that the InfiniteScroll component receives a new hasMore prop and new children (aka items in list). This happens only in 1 of my cases though. Currently investigating!

bug better

Expose isElementAtBottom as a property?

Hi,

I am developing with the dev tools open and "toggle device toolbar" on (to display the viewport as a mobile device. (Also, I'm using scrollableTarget).

With this setup, next is never firing. i.e. the following is always returning false:

  isElementAtBottom (target, scrollThreshold = 0.8) {
    const clientHeight = (target === document.body || target === document.documentElement)
    ? window.screen.availHeight : target.clientHeight;

    const scrolled = scrollThreshold * (target.scrollHeight - target.scrollTop);
    return scrolled * (window.devicePixelRatio || 1) <= clientHeight;
  }

Can you please confirm that this is an issue (and that I'm not using the component improperly)?

If you'd like the change, I can look into exposing isElementAtBottom as a property (shouldn't be hard to do but I haven't really looked at all the code).

Thank you

Infinite Scroll targeting on a parent div does not load the details

While targeiiing a outer div than the immendiate parent div for infinite scroll, function call happends for
next property but the items does not load in the UI.

Code Sample

<InfiniteScroll

                                next={this._loaditems.bind(this) }
                                hasMore={this.state.hasMoreItems}
                                scrollableTarget= {this._returnParent() }
                                scrollThreshold={0.5}
                                >
                                <DetailsList
                                    items={this.state.items}
                                    columns={_itemColumns}
                                    layoutMode={DetailsListLayoutMode.fixedColumns}
                                    checkboxVisibility={CheckboxVisibility.hidden}
                                    compact={true}
                                    onRenderRow={this._onRenderitem.bind(this) }
                                    />
                            </InfiniteScroll>

//this._returnParent() - returns the parent div object.

Edge Scrolling issue

It seems to me that without adding the height prop, the scrolling is not working in edge. It even worked in IE. Can anyone confirm it?

Odd behavior with nested InfiniteScrolls

I've got an app with a potentially-large tree-list, e.g.

  • Parent Item 1
    • Child Item 1A
    • Child Item 1B
    • ...
  • ...
  • Parent Item 100
    • Child Item 100A
    • ...

Where parent items can be expanded and collapsed by the user, and child items may in turn have their own children. I'm trying to utilize react-infinite-scroll-component to improve the performance of the initial rendering of this tree, but have run into strange behavior when the InfiniteScroll components are nested.

See https://codesandbox.io/s/p75kz97j87

If the "MegaList" button is selected, you'll start out with 5 parent elements each with 5 children. You can clearly see the end of the "Parent Number 1" child list, but it doesn't advance that list until you've scrolled down far enough that the outer list decides to load "Parent Number 6". At that point if you scroll back up, you'll see that "Parent Number 1" has loaded 10 children. You can bounce back and forth between the bottom and the top of the page to get it to load more child elements, but obviously this is not intended behavior.

I'd expect "Parent Number 1" to load its children as I scroll, so that I don't see "Parent Number 2" until all of the "Parent Number 1" child elements have loaded.

This might be somewhat related to #47 - you'll notice if you click the "InnerList" or "OuterList" buttons, you'll get a UI with 5 child elements, but it should be InfiniteScrolling to reveal up to 100. If you make the window short enough to have a scrollbar, you can get them to load more by scrolling.

How to "re-calc" the height of the body?

First, thanks for the component is very handy!

I have a question, in my use case, I render as children of the component embedded tweets using this library: https://github.com/capaj/react-tweet-embed.

I am having a problem, the "next" is called multiple times and way before the 80%, I am pretty sure that is because the embedded tweets are created after the first rendering happened, so the height when the full view is rendered is way different than the initial one.

Is there a way to avoid this problem? Maybe forcing a re-calc on the component?

Hiding endMessage is not intuitive.

I just wanted to hide the endMessage but doing so it not intuitive, setting it to '', false or null just shows the default, you have to set it to ' ' to actually hide the message when you don't want to show anything (including the cute default).

scrollableTarget not trigger

Hi !!
I am having some trouble with scrollableTarget prop.
When I set the prop, the next function never gets triggered.
It seems that I am doing something wrong but I can't see what ...

Here is some part of my code:

<Grid.Column width={11} id='billList' className='bill-content fdx-content bill-list-container'>
              <InfiniteScroll
                dataLength={this.props.bills.length} //This is important field to render the next data
                next={this.loadBills}
                scrollableTarget={document.getElementById('billList')}
                onScroll={()=> {console.log(document.getElementById('billList'))}}
                hasMore={this.state.hasMore}
                loader={<Loader status={this.props.isFetching} />}
                endMessage={
                  <p style={{textAlign: 'center'}}>
                    <b>Yay! You have seen it all</b>
                  </p>
                }>
                  <BillList
                    localId={local.id}
                    token={token}
                    getBills={getBills}
                    openSidebar={this.openSidebar}
                    isSidebarOpen={isSidebarOpen}
                    bills={this.props.bills}
                  />
                </InfiniteScroll>
            </Grid.Column>

I have a 'Grid' parent div which has billList as ID. This means that the InfiniteScroll is not working with the div scroll.
Besides, if I set a particular height to the InifniteScroll component the onScroll function logs all actions.

I have also looked for some examples with the scrollableTarget option working, but it seems that there is any one in the repo.

I hope you can help me !!

Guido

Nesting element (div) in endMessage throws warning

Currently implementing this component however, I don't think it makes sense that the endMessage prop only takes text. Should be able to just pass component without any styling by this component.

When I pass it a div with some content it throws the following error:

Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>. See ReviewList > InfiniteScroll > p > ... > InfoBox > div.
Please fix this issue ;) I've never made a pull request and don't have a clue on how to do it ;)

Expected a component class, got [object Object]

I do as shown in the example, but says it wants to component was

<InfiniteScroll 
  pullDownToRefresh
  pullDownToRefreshContent={<h3 style={{textAlign: 'center'}}>&#8595; Pull down to refresh</h3>}
  releaseToRefreshContent={<h3 style={{textAlign: 'center'}}>&#8593; Release to refresh</h3>}
  refreshFunction={this.refresh}
  next={this.generateDivs}
  hasMore={true}
  loader={<h4>Loading...</h4>}>
  {[
    <div key={2} style={{height: 200, background: '#ffd47b'}}>Div no 2</div>,
    <div key={1} style={{height: 200, background: '#9bc95b'}}>Div no 1</div>,
    <div key={3} style={{height: 200, background: '#95a9d6'}}>Div no 3</div>,
    <div key={4} style={{height: 200, background: '#ffa8e1'}}>Div no 4</div>,
    <div key={5} style={{height: 200, background: '#9bc95b'}}>Div no 5</div>,
    <div key={6} style={{height: 200, background: '#ffd47b'}}>Div no 6</div>,
    <div key={7} style={{height: 200, background: '#95a9d6'}}>Div no 7</div>,
    <div key={8} style={{height: 200, background: '#ffa8e1'}}>Div no 8</div>,
  ]}
</InfiniteScroll>

img

# I copied this example all exactly the same error

https://github.com/ankeetmaini/react-infinite-scroll-component/blob/master/demos/height.js

2-way scroll

I have a proposal for the new feature.
It would be nice if the component had an option to infinite scroll in both directions.
It would be useful on timelines where you start in the middle. For example when you want to show present, but also want to be able to scroll into the past or future.

Remove Throttle Effect

Is there a way to remove throttle? When we scroll fast the events are not captured & results in lagging behavior.

Keep scroll on same position

Hello,

How to keep the scroll in same position when i unshift and render new item in list( this.renderConversations() in this function i have a loop on redux state list) ?

If i update existing item in the list the scroll keep same position.Only when i add new item in list scroll loose position.Thank you!
`

<InfiniteScroll
dataLength={conversations.list.length}
next={() => this.props.fetchMoreUnreadedConversations(conversations.next_page_url)}
hasMore={(conversations.next_page_url)}
height={440}
useWindow={false}
loader={

Loading...

}
pullDownToRefresh
pullDownToRefreshContent={
<h3 style={{textAlign: 'center', color: '#FFF'}}>↓ Pull down to refresh
}
releaseToRefreshContent={
<h3 style={{textAlign: 'center', color: '#FFF'}}>↑ Release to refresh
}
refreshFunction={() => {
console.log('refresh')
}}>
{this.renderConversations()}

`

scrollableTarget not working

Hi, i was having trouble while using infinite scrolling, because data was being loaded when my browsers main window scrollbar scrolled. So i tried using scrollableTarget to fix the problem, but when i tried using it the loader keeps displaying and no data is fetched. Code looks like this:

<Container id="divID">
        <InfiniteScroll
          dataLength={this.state.logs.length}
          next={this.fetchMoreData}
          hasMore={true}
          loader={<Loader />}
          scrollableTarget="divID"
        >
          <Table striped>
            <thead>
              <tr>
                <th>...</th>
                <th>...</th>
                <th>...</th>
              </tr>
            </thead>
            <tbody>
              {this.state.logs.map(event => (
                <tr key={event.id}>
                  <td>....</td>
                  <td>....</td>
                  <td>....</td>
                </tr>
                    ))}
            </tbody>
          </Table>
        </InfiniteScroll>
</Container>

Here you can see the id of Container
screen shot 2018-05-28 at 00 25 05

I Also tried using scrollableTarget=document.getElementById("divID") and it now renders the content but it only loads more data when the main window scrollbar moves not when the one in my Table element does.

Usage example for static data

Hi,

I would like to use this on a large list of static/offline data. However, I have been unable to implement it. Basically, I want it to only get say 100 results from the map at this.state.demoData. Then once I reach the refresh point, it should get 100 more results.

I am wanting to use infinite scroll to improve performance (as the list will be long, and have a lot of data in it such as images )

I have not been able to implement it. I put this in a codeSandBox https://codesandbox.io/s/xvlR245VE

Here is my code:

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      demoData: x.demoData,
    };
  }
  generateDivs = () => {
    let moreDivs = [];
    let count = this.state.demoData.length;
    for (let i = 0; i < 30; i++) {
      moreDivs.push(
        this.state.demoData.map(e => {
            <span key={e.id}> {e.name} </span>
        }));
    }
  }
  render() {
    return (
        <div style={{overflow: 'auto', maxHeight: 500}}>
test
        <InfiniteScroll
          next={this.generateDivs}
          hasMore={true}
          loader={<h1>Loading...</h1>}>
          {this.state.demoData}
        </InfiniteScroll>
      </div>
    );
  }
}

I've also put it in a code sandbox:

https://codesandbox.io/s/xvlR245VE

Large screen

Hi,

I just integrated the component in my application and seems work perfect.

When the screen is large enough to show all the items (for example, 10 items), there is not scroll bar. At that moment, the component don't work.

Please, may I know your suggestion?

Thanks!

Problem with styling

I've problem with styling when component is in the middle of context.

<div></div>
<div>There I have component</div>
<div></div>

And the InfiniteScroll makes a div around him and there is no way to inherit hight from outer component. The only solution which I found is to change line:
From var outerDivStyle = this.props.pullDownToRefresh && this.props.height ? { overflow: "auto" } : {};
To: var outerDivStyle = this.props.pullDownToRefresh && this.props.height ? { overflow: "auto", height: "inherit" } : {};

screen shot 2018-05-20 at 14 40 11
As you can see height:"inherited" was set in InfiniteScroll props but it inherits from this outerDiv instead of parent.

Also I don't want to specify constant height due to responsiveness of app.

Question about pulldown

I really like the pull-down functionality a lot, however when webapps are added to a home screen and you pull down to refresh inside the react element you also get the circle of the webbrowser (see picture below).

screenshot_20170415-134348

Suggested workarounds (not tested)

Maybe add it to the readme or docs? :)

Cannot find module './factoryWithTypeCheckers'

I'm getting this error when compiling:
Error: Cannot find module './factoryWithTypeCheckers' from '.../node_modules/react-infinite-scroll-component/lib'

I'm using react 16.6

Any help is appreciated

Bidirectional infinity

This component has been an enormous help but (I fear) it has a fatal flaw for part of my use case.

I have a list of ~100k alphabetized names in my large touchscreen table application. While the enormous task scrolling through it is actually a key part of the interaction, sometimes the user has other needs and I've given them a set of letter buttons to jump around in the list. The approach of just rewriting the divs array is fairly satisfying until they want to scroll up. I'm currently surviving by using refreshFunction to prepend a new page of data on divs which obviously causes a flash rather than a scroll. Is there a ReactJS-y way to access where the 'top' of the scrolling div is going to start?

The `next` method should not be called again when the loader is still being shown

Curerntly when I reach the bottom in the component it triggers the next method which is perfect. However while the loader is still being shown (aka the data is not yet finished fetching), the next method triggers again.

I believe that the next method should have a simple state key which could be isWaiting. This would be true if the Loader is being shown.

Scroll doesn't work fine

Hi
I used your component and when I scroll down it worked fine once
but at the second time I should scroll up and down to perform loading data
and it doesn't work if I just scroll down

Expose a prop to set callbacks for scroll event

I need an ability to store the current scroll position of the list so that I can reset the scroll position when the component is rendered.

For a regular div, this could be done by storing the scroll position on the scroll event and restoring this in the component's didMount.

Could we expose a prop to register a callback that will be called at the end of onScrollListener? I don't think the throttling will be an issue for anyone wanting to use this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.