Coder Social home page Coder Social logo

react-window's People

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  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

react-window's Issues

Horizontal overflow on VariableSizeGrid

Similar to #22. Except this time it's for VariableSizeGrid. I've created a few examples to demonstrate.

Horizontal scrollbar appears on OSes with always visible scrollbars (e.g. Windows) once scrolled a bit:
https://codesandbox.io/s/r55m5n027n

The same issue could be reproduced on other OSes (e.g. macOS) when using custom scrollbars via :-webkit-scrollbar:
https://codesandbox.io/s/618026v83r

The only workaround I've found is to offset each column by scrollbar width:
https://codesandbox.io/s/l2rqwyv989

Ofc then we have to know the scrollbar width beforehand either using a constant width when we have custom scrollbars or using some kind of width detection mechanism (calculating from elm.clientWidth - elm.offsetWidth). The latter sounds more ugly and could lead to jank when called to frequently. But then again, we would only need to calculate scrollbar width once in user's session.

scrollToItem + changing number of items sometimes glitches

I'm writing a file listing widget using FixedSizeList, and after changing to a different folder, I want to scroll back to the top. This sometimes causes the bottom half of all items to disappear, see this codesandbox:

https://8zm2lzr10j.codesandbox.io/

I noticed that in the broken state, there is a negative scrollOffset. That's about as far as I got with debugging.

Tested with react-window 1.1.1 on Chrome 68.0.3440.106 on Linux, Firefox 60.1.0esr (64-bit) on Linux.

Item never appear if scrolling to fast

This snippet below stops rendering items if I scroll to fast. Not sure why, The list I have right now while in dev is about 1600 elements. However the real list will be at the minimum 400k elements. There are no errors in the console that can point to any reason why this might be happening.

<div>
  <h2>
    Results(
    {listItems.length})
  </h2>
  <List
    itemCount={listItems.length}
    itemSize={50}
    height={this.state.height}
    width={400}
  >
    {({ index, style }) => (
      <div
      style={style}
      className={css(styles.searchItem)}
      style={styles}
    >
      <p>{listItems[index].properties.id}</p>
      <p>Score: {listItems[index].properties.score}</p>
    </div>
    )}
  </List>
</div>

react-window

position sticky headers

Curious if there is a way to hook into react-window to allow use of position sticky? Similar to https://github.com/marchaos/react-virtualized-sticky-tree. As a quick test I tried rendering a larger row with sticky headers, but it doesn't seem to be working. Seems like we would need some hooks or a way to tell the header to stay in view for so many pixels 🤔. Still working on things and will report back with whatever I find, just wanted to see if this has been thought about or explored yet.

Code samples on website do not match displayed element

For example, on the example of the Fixed Size List, items in the row are labelled "Item n" in the demo, but Row {index} in the code sample.

image

I wanted to submit a PR to fix this, but since code examples are reused (e.g. FixedSizeList in both Fixed Size List as Scrolling to an item), I couldn't simply modify them, and since the horizontal and vertical versions of the Fixed Size List both reuse the code that labels them with "Item", I could change the demo elements either. (I also didn't manage to quickly get it to run locally by following the instructions in website/README either, btw...)

VariableSizeGrid does not clear clear cache and does not reapply new styles

Everything works fine when rowHeight or columnWidth selectors never change, but when they do change, rows and columns that were already rendered do not get their styles updated.

I've created an example sandbox with AutoSizer for this issue:
https://codesandbox.io/s/2p1jrywm30

When width of the element changes, e.g. user changing width of the window, AutoSizer updates the width and height, but VariableSizeGrid does not refresh those values. I would expect that cache should be invalidated and new styles should be calculated and applied to the children.

Support just-in-time measured content

In order to avoid adding cost to existing list and grid components, create a new variant (e.g. DynamicSizeList and DynamicSizeGrid). This variant should automatically measure its content during the commit phase.

MVP

The initial implementation of this could work similarly to how CellMeasurer works in react-virtualized:

  1. Content is measured only if no current measurements exists.
  2. Measurements need to be reset externally (imperatively) if something changes.
  3. Cells at a given index can only be positioned after all cells before that index have been measured.

Goal

This component could perform better if we removed the third constraint above, allowing random access (by either item index or scroll offset) without measuring the preceding items. This would make react-window much more performant for use cases like chat applications.

This would also unlock the ability to use a ResizeObserver (via react-measure) to automatically detect item sizing and remove the position and measurements cache entirely. This would remove the need for imperatively resetting cached measurements and dramatically improve the API.

In order for the above to be possible, the dynamic list/grid components would need to use a dramatically different approach for mapping offset to index and vice versa. (This comment about "scroll anchoring" in react-virtualized has some nice visuals.) Essentially, we would need to do something like this:

  • Estimate total size based on the number of items multiplied by a estimatedItemSize prop. (This estimated size won't need to be adjusted, since the mapping described below doesn't is fuzzy.)

  • When scroll position changes, compare the new offset to the previous offset. If the delta is greater than some [to be determined] threshold, set the new offset as the "scroll anchor". Map the offset to an estimated index (e.g. divide the offset by total estimated scrollable size and multiply that by the number of items in the collection). Store this mapped index as the "anchor index". For example, if the list described by the image below had 250 items, the "anchor index" would be 132.

screen shot 2018-06-10 at 11 58 38 am

  • When scroll position changes, if the delta is less than the threshold, choose which new items to render relative to the anchor index. Position these items relative to the previously positioned items. Continuing with the example above, if the list was scrolled by a small amount (200px) then 200px worth of additional rows would need to be appended below the previously positioned items:

screen shot 2018-06-10 at 12 01 01 pm

The above approach has only one major downside: aligning items correctly at list boundaries. If item indices are estimated (as described above) then they likely won't line up exactly with the beginning or end of the scrollable area.

  • The end could potentially be accounted for by adjusting the total estimated size as the user scrolls closer to the end (although this might make scrolling feel janky).

  • The start of the list is harder to handle, since the first item needs to align with offset zero while still appearing to connect contiguously with items from some offset greater than zero. Perhaps another threshold could be used, a "safe zone", near the start of the list (e.g. if the scroll offset is less than some absolute value) which would force the list to measure all cells up to that point so they align correctly. The cost of this forced measurement would be relatively low, since it would only be a small number of items.

screen shot 2018-06-10 at 5 04 42 pm

The one case that would still not be handled correctly with the above approach would be a scroll anchor that is set outside of the "safe zone" but a current scroll that goes inside of the safe zone (as shown below). If the user scrolls slowly back toward the beginning of the list, it may be difficult to align the first cell with zero without introducing scroll janky.
screen shot 2018-06-10 at 5 08 26 pm

IOS Safari elasticity

May be it's well known issue, but for safari IOS all the controls with both scroll (horizontal and vertical) allowed in one div become a pain.
Scrolling because of scroll elasticity looks like
kapture 2018-07-24 at 2 00 29

It's reproduced on real devices, and all that jumps too. Unfortunately safari has no some kind of directionalLockEnabled feature, and does not support overscroll-behavior css prop.

To avoid we splitted scrolls across 2 different divs (one with y scroll enabled and other with x), in that case scroll works in one general direction, and there is no such jumps.

The problem of such solution that it hides right scroll from a window (horizontal scroll is placed at the right of table which is wider than window)

Just a question haven't you think about this problem and possibly know the solution?

Thank you for this lib, amazing!

FixedSizeList padding

Is there a way to have padding at the top and bottom of a list? If I do 10px 0 on the outer div I get 20px of padding at the bottom, I can make it look proper by adding a 10px top margin to the list items but that just shifts the windowing off-center.

Animating .scrollTo() / .scrollToIndex() ❓

Hi there :)

Thanks for this great lib!

I'm experimenting with it and I wondered whether it's somehow possible to animate the scrolling behavior ("smooth scroll") when using scrollTo() / scrollToIndex()?

problem with getEstimatedTotalSize

I'm working on a select component with VariableSizeList of react-window and it works perfect, but when I search to narrow down the result (and the menu's height will update), the innerRef's clientHeight is wrong as getEstimatedTotalSize is not works right with dynamic data

const getEstimatedTotalSize = (
  { itemCount }: Props,
  { itemMetadataMap, estimatedItemSize, lastMeasuredIndex }: InstanceProps
) => {
  let totalSizeOfMeasuredItems = 0;

  if (lastMeasuredIndex >= 0) {
    const itemMetadata = itemMetadataMap[lastMeasuredIndex];
    totalSizeOfMeasuredItems = itemMetadata.offset + itemMetadata.size;
  }

  const numUnmeasuredItems = itemCount - lastMeasuredIndex - 1;
  const totalSizeOfUnmeasuredItems = numUnmeasuredItems * estimatedItemSize;

  return totalSizeOfMeasuredItems + totalSizeOfUnmeasuredItems;
};

The problem is that if the itemCount changes from 100 to 1, lastMeasuredIndex is larger then 1, so we can't rely on it anymore

Currently I solved the problem by pass key={itemCount} to List to make a refresh calculation. So perhaps that's not a bug, but I think we should denote that it could be problematic with dynamic data

Awesome

Love the size and focus of this library. Been looking for something like this to use as simpler foundation for these type of components. Thanks for reworking your ideas in this form!!

Grid column headers

Perhaps this new version would include column headers for the Grid control. Use rowIndex = -1 for the header row. On each render of the Grid, rowIndex -1 would be the first row called for.

overscanCount = 0?

Hi :)

I was wondering whether you'd consider to allow actually setting overscanCount value of 0.
Currently the required minimum is 1 to enable tabbing, which is completely understandable.

However, I am currently working on a case where the rendered items are rather expensive and tabbing is not important/disabled on purpose so I'd really appreciate a way to override this.

Thanks for your consideration!

would this be a standalone library

I created a complex Table component based on Grid of react-virtualized, I'm rewriting it now, and I'm not sure that should I use this library directly or wait for it being merged into react-virtualized as v10.

I love the simplicity of this library compare to react-virtualized, seems the original purpose of this repo is an api experimental for react-virtualized v10, I'm using some apis like onScrollbarPresenceChange from react-virtualized which are not available in this library, but I could implement them on my side if I choose to use this library. So I want to make sure what's the future of this library.

data prop in children props is undefined

When I log the children component props,

const Row = (props) => {
  console.log('-----', props)
  return (
    <div>#{props.index}</div>
  )
}

image

the data prop in props is undefined, why an undefined value is passed to the children component?

Here is the source code

// ...
        createElement(children, {
              data: itemData,
              key: itemKey(index),
              index,
              isScrolling: useIsScrolling ? isScrolling : undefined,
              style: this._getItemStyle(index),
         })

// ...

The itemData is from the props.

Compiled code seems broken

Calling e.g. ref.current.resetAfterColumnIndex() on VariableSizeGrid seems to trigger a runtime error.

Resize the window of this Code Sandbox to repro: https://codesandbox.io/s/5ywr9ro7nn

It looks like the this context is getting messed up somehow. (this is valid but _this is undefined.)

Blank spots while scrolling

I'm seeing a lot of white while scrolling (screen cap below) in a list of 3xx items. They're all connected items, though (as in they're bound to a store), does this make a difference? Are elements re-created or cloned in order to virtualize them? I don't have that problem in the react-window demos, and they seem to have tons of items more, i wonder what's causing it for me ... 🤔

rw

And a quick screenshot of the code that produces the list:

screenshot 2018-08-15 at 16 11 46

Fetch more from remote

Is it possible to fetch more data from the remote location if the scroll is at the end? If yes, how would I build this? If not I would love to help adding that feature 👍 .

VariableSizeList can call itemSize getter with an invalid index

Hey,

I recently ported a list over to react-window and I noticed that under certain circumstances the itemSize callback can be called with an invalid index.

My code is basically

                <VariableSizeList
                  height={height}
                  width={width}
                  ref={this._setRef}
                  onItemsRendered={this._onItemsRendered}
                  itemCount={this.props.rows.length}
                  itemSize={this._itemSizeGetter}
                  estimatedItemSize={56}
                >
...
  _itemSizeGetter = index => {
    if (this.props.filter.length) {
      return 56
    }
    const row = this.props.rows[index]

so itemCount is based on this.props.rows so that should always be synced up.

From what I've seen itemCount is 0 and since (https://github.com/bvaughn/react-window/blob/master/src/VariableSizeList.js#L42)

    for (let i = lastMeasuredIndex + 1; i <= index; i++) {
      let size = ((itemSize: any): itemSizeGetter)(i);

the i <= index allows this to be out of bounds

Dynamic heights on each item

Hi,

What I'm looking to do is have each items height be dynamic based on it's content.

This can be achieved by getting the clientHeight value from the refs of list items, capturing that to state (as an array or map object) and passing that value back to the itemSize function. However, a value itemSize is initially required. If I give it a value, then the clientHeight will always be that value.

Can anyone point me in the right direction? Much appreciated, thanks!

Fixed/Sticky Columns

Is it within the scope of this library to have some way to mark columns as being fixed/sticky?

Eg. having the cells in the first 2 columns of a VariableSizeGrid not scroll horizontally while the rest of the cells do?

Currently I have other code that takes care of fixing these cells, but that is preventing me from using the *Grid components to handle horizontal scroll windowing. Given the complexity of the some of the cell contents this can cause a the rows to take a long time to pop in while/after scrolling.

If this is not currently possible and within the scope of the library I would be willing to look at opening a PR to add this functionality.

Using html table element

Do you have an example of using this with tables? I'm trying to get it working but I have a strong suspicion that it either doesn't work, or that I'm doing something very wrong.
I've set the outerTagName to "table" and the innerTagName to "tbody", but I don't get any scrolling.

Here is my code, not sure if it helps (items is a list of objects):

 <List
            outerRef={this._list}
            outerTagName="table"
            innerTagName="tbody"
            height={300}
            itemData={items}
            itemSize={() => 30}
            itemCount={items.length}
            itemKey={item => item.uniqueId}>
            {({index, style, data}) => {
              return (
                <tr style={style} key={index}>
                  <td>Item {index}</td>
                </tr>
              );
            }}
          </List>

Dynamic pre-rendering / over-rendering

Relates to this Twitter thread:
https://twitter.com/Vjeux/status/1008077144289787904

Since the scrolling thread can get ahead of the UI thread, windowing libraries sometimes show blank space in the direction being scrolled (especially for sudden, quick scrolling).

It might be possible to use a heuristic based on the scroll delta and the time between commits (i.e. componentDidUpdate calls) to render ahead of where the scroll position currently is. This might enable us to reduce the amount of visible white space when scrolling quickly.

This heuristic would need to take the state.scrollUpdateWasRequested value into consideration so that programmatic scroll-jumps wouldn't cause us to render ahead.

Non-stop re-rendering

I'm having a non-stop re-rendering.
In this simple example, I'm just rendering div containing "X".
I gave it the right height and width, tried to remove every possible CSS and I just can't get it.

Elements:
ezgif com-crop

Screen:
ezgif com-video-to-gif

my code:

<div>
        <List
                height={200}
                itemCount={this.state.filteredValues.length}
                itemSize={17}
                width={682}
                overscanCount={10}
            >
                {({ index, style }) => (
                    <div> X </div>
                )}
            </List>
    </div>

Windowscroller

Thanks for your work on this, looks really impressive 🎉

I am interested if you are open to add windowscroller functionality in this library or if that is out of scope for this library perhaps because of performance reasons.

In our app we make use of react-virtualized at this moment, but it's always great to switch to a more performant alternative. If I can find time, I am interested to help out with the implementation of the windowscroller functionality.

Negative offset in VariableSizeList

I am rendering a VariableSizeList component which has fewer items than its height and therefore is not scrollable at first, but more rows are added later which then requires scrolling. However, the rows added are not shown.

Here is what I think what happens:

  • VariableSizeList is rendered with a few items, which don't require scrolling
  • I call scrollToItem() (this is called after adding rows because I want the list to be always scrolled to the bottom.
  • the internal scrollOffest in state set to a negative value (I see this from react-devtools)
  • new rows are added, but because of the negative value in scrollOffset they are assumed to be out of view and therefore not rendered.

I did some logging from the library and see maxOffset is negative here https://github.com/bvaughn/react-window/blob/master/src/VariableSizeList.js#L191
When manually setting the scrollOffest to 0 using react-devtools the missing rows are rendered.
Is there a case why the scrollOffset should ever be negative? Otherwise, I would suggest adding Math.max(0, maxOffset) there.

This might also affect FixedSizeList or the Grid components, I haven't tested with them.

[Q] About animating and dynamically growing items

First thanks for the great work on that library!

I was asking myself a question about items animation. I have been using react-virtualized so far, but it also applies to react-window.

The current positioning strategy is to use absolute offset based on scroll position, right? Which makes it difficult to use CSS techniques to animate items. JS techniques are also problematic if they involve re-rendering the whole list each frame.

Do you have a suggestion on the best way to implement this? Typically, think about a contact card in a contact list, that can be expanded with more info.

Do you think static positioning would work? For example, by adding a transparent div the size of the items prepending the windowed items? (yes I mean me developing another custom solution for my specific purpose, but I wanted to ask the question as you explored this a lot more and migh see the obvious issues with this strategy :))

Can't get ref= to work properly

Hi There! Big fan of the library so far. I'm having an issue getting the ref logic to work for the scrollTo functionality (trying to mimic ScrollSync functionality from react-virtualized).

Also, please let me know if this is a poor use of issues.

React Version: "16.4.2"
React Window: "1.1.2"

The <Grid> component is calling this.syncHeaderScroll in the onScroll prop.

I was hoping syncHeaderScroll would look something like this:

  syncHeaderScroll = ({ scrollLeft }) => {
    if (this.listRef.current) {
      this.listRef.current.scrollTo(scrollLeft)
    }
  }

I'm trying to make sure I'm not missing anything. When I console.log this.listRef.current I'm just getting null.

Code snippet here:

export class ActivityStream extends PureComponent {
  listRef = React.createRef()

  syncHeaderScroll = ({ scrollLeft }) => {
    console.log("this.listRef.current", this.listRef.current)
  }

  render() {
    return (
      <Fragment>
        <List
          direction="horizontal"
          ref={this.listRef}
          height={HEADER_HEIGHT}
          itemCount={ACTIVITY_STREAM_HEADERS.length}
          itemData={ACTIVITY_STREAM_HEADERS}
          itemSize={index => ACTIVITY_STREAM_COLUMN_WIDTHS[index]}
          width={tableWidth}
        >
          {props => <HeaderRenderer filters={filters} onOpenFilter={this.handleOpen} {...props} />}
        </List>

        <Grid
          columnCount={ACTIVITY_STREAM_HEADERS.length}
          columnWidth={index => ACTIVITY_STREAM_COLUMN_WIDTHS[index]}
          estimatedRowHeight={DEFAULT_ROW_HEIGHT}
          height={windowHeight - 250}
          itemData={itemData}
          overscanCount={10}
          rowCount={rowData.length}
          rowHeight={index => {
            const { first_session_activity, last_session_activity } = rowData[index]

            if (first_session_activity && last_session_activity) {
              return DEFAULT_ROW_HEIGHT + DIVIDER_BOTTOM_MARGIN + BORDER_WIDTH * 2
            }

            if (first_session_activity) {
              return DEFAULT_ROW_HEIGHT + DIVIDER_BOTTOM_MARGIN + BORDER_WIDTH
            }

            if (last_session_activity) {
              return DEFAULT_ROW_HEIGHT + BORDER_WIDTH
            }

            return DEFAULT_ROW_HEIGHT
          }}
          width={tableWidth}
          onScroll={this.syncHeaderScroll}
        >
          {ItemRenderer}
        </Grid>
      </Fragment>
    )
  }

Footer prop?

I am trying to show a spinner at the end of the list when more data is getting fetched.

I can't seem to find a better way other than adding a footer component after inner container:

<outer>
  <inner><item/>...</inner>
  <footer/>
</outer>

@bvaughn is this something that you would want to add?

Smooth scrolling (or Animations)

Hi Brian,

thanks for an awesome work.

Is it possible somehow to scroll smoothly? e.g. scrolling will not jump directly to a specified row.

Thanks.

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.