React-window: λ°˜μ‘ 창으둜 μ‚¬μš©μž μ •μ˜ μŠ€ν¬λ‘€λ°” λ°˜μ‘

에 λ§Œλ“  2018λ…„ 12μ›” 17일  Β·  35μ½”λ©˜νŠΈ  Β·  좜처: bvaughn/react-window

λ‚΄κ°€ μ‚¬μš©ν•˜κ³  react-custom-scrollbar ν•˜κ³ μ™€ ν†΅ν•©ν•˜λ €λŠ” FixedSizeList .

이 λ¬Έμ œμ— λŒ€ν•œ 해결책을 react-virtualized : https://github.com/bvaughn/react-virtualized/issues/692#issuecomment -339393521

κ·ΈλŸ¬λ‚˜ μ½”λ“œλŠ” λ‹€μŒ ν•¨μˆ˜μ—μ„œ μŠ€ν¬λ‘€μ‹œ Uncaught TypeError: Cannot read property 'handleScrollEvent' of undefined 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.

  handleScroll = ({ target }) => {
    const { scrollTop, scrollLeft } = target;

    const { Grid: grid } = this.List;

    grid.handleScrollEvent({ scrollTop, scrollLeft });
  }

fixedSixe <List ꡬ성 μš”μ†Œμ— ref={ instance => { this.List = instance; } } 을 μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.

πŸ’¬ question

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

더 λ‚˜μ€ 방법은 Scrollbars λ₯Ό outerElementType

const CustomScrollbars = ({ onScroll, forwardedRef, style, children }) => {
  const refSetter = useCallback(scrollbarsRef => {
    if (scrollbarsRef) {
      forwardedRef(scrollbarsRef.view);
    } else {
      forwardedRef(null);
    }
  }, []);

  return (
    <Scrollbars
      ref={refSetter}
      style={{ ...style, overflow: "hidden" }}
      onScroll={onScroll}
    >
      {children}
    </Scrollbars>
  );
};

const CustomScrollbarsVirtualList = React.forwardRef((props, ref) => (
  <CustomScrollbars {...props} forwardedRef={ref} />
));

// ...

<FixedSizeList
  outerElementType={CustomScrollbarsVirtualList}
  {...rest}
/>

예 https://codesandbox.io/s/vmr1l0p463

λͺ¨λ“  35 λŒ“κΈ€

이 λΌμ΄λΈŒλŸ¬λ¦¬μ™€ react-virtualized 은 μ™„μ „νžˆ λ‹€λ₯Έ κ΅¬ν˜„μž…λ‹ˆλ‹€. react-virtualized λ¬Έμ œμ—μ„œ λ³Ό μˆ˜μžˆλŠ” 일반적인 κΈ°μˆ μ€ μ’…μ’… μ ‘κ·Ό 방법에 λŒ€ν•œ μœ μš©ν•œ 힌트λ₯Ό 제곡 ν•  수 μžˆμ§€λ§Œ 이와 같은 ꡬ체적인 κ΅¬ν˜„ μ„ΈλΆ€ 사항은 적용 ν•  수 μ—†μŠ΅λ‹ˆλ‹€. ( react-virtualized μ—μ„œ List λŠ” Grid ꡬ성 μš”μ†Œλ₯Ό μž₯μ‹ν•©λ‹ˆλ‹€. react-window μ—μ„œλŠ” μ„±λŠ₯κ³Ό 크기λ₯Ό κ°œμ„ ν•˜κΈ° μœ„ν•΄ λ³„λ„μ˜ ꡬ성 μš”μ†Œμž…λ‹ˆλ‹€.)

react-custom-scrollbar 와 같은 것이 react-window 와 (와) ν•¨κ»˜ μž‘λ™ν• μ§€ λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€. μ†”μ§νžˆ λ§ν•΄μ„œ μ§€μ›ν•˜κ³  싢은 것은 μ•„λ‹™λ‹ˆλ‹€. μ»€μŠ€ν…€ μŠ€ν¬λ‘€λ°”λŠ” μ„±λŠ₯에 λ―ΈμΉ˜λŠ” 영ν–₯ λ•Œλ¬Έμ— 일반적으둜 λ‚˜μœ 생각이기 λ•Œλ¬Έμž…λ‹ˆλ‹€. κ·Έλž˜μ„œμ΄ 문제λ₯Ό λ§ˆλ¬΄λ¦¬ν•˜κ² μŠ΅λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ 후속 질문이 있으면 계속 μ±„νŒ… ν•  수 μžˆμŠ΅λ‹ˆλ‹€ πŸ˜„

이것에 λŒ€ν•΄ λ­”κ°€ μ•Œμ•„λ‚Ό κ²ƒμž…λ‹ˆλ‹€. react-window μ‚¬μš©μ— 관심이 μžˆμŠ΅λ‹ˆλ‹€. 가볍고 문제λ₯Ό ν•΄κ²°ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. λ‚˜λ„ μ‚¬μš©μž 지정 μŠ€ν¬λ‘€λ°”λ₯Ό μ‚¬μš©ν•˜λŠ” 것을 μ’‹μ•„ν•˜μ§€ μ•Šμ§€λ§Œ λ‚΄ 손 μ•ˆμ— μžˆμ§€ μ•ŠμœΌλ―€λ‘œ μŠ€ν¬λ‘€λ°”μ— λŒ€ν•œ μ‚¬μš©μž 지정 λ””μžμΈμ΄ ν•„μš”ν•©λ‹ˆλ‹€.

μ΅œμ•…μ˜ 경우 react-virtualized ν•©λ‹ˆλ‹€.
감사 :)

@ Rahul-Sagore 당신은 react-window 와 ν•¨κ»˜ μž‘λ™ν•˜λŠ” μ‚¬μš©μž μ •μ˜ μŠ€ν¬λ‘€λ°”λ₯Ό μ–»μ—ˆμŠ΅λ‹ˆκΉŒ?

μ•„λ‹ˆ, 그럴 μ‹œκ°„μ΄ μ—†μ—ˆμ–΄. ν™•μΈν•˜κ³  μ•Œμ•„λ‚Ό ν•„μš”κ°€ μžˆμŠ΅λ‹ˆλ‹€.

더 λ‚˜μ€ 방법은 Scrollbars λ₯Ό outerElementType

const CustomScrollbars = ({ onScroll, forwardedRef, style, children }) => {
  const refSetter = useCallback(scrollbarsRef => {
    if (scrollbarsRef) {
      forwardedRef(scrollbarsRef.view);
    } else {
      forwardedRef(null);
    }
  }, []);

  return (
    <Scrollbars
      ref={refSetter}
      style={{ ...style, overflow: "hidden" }}
      onScroll={onScroll}
    >
      {children}
    </Scrollbars>
  );
};

const CustomScrollbarsVirtualList = React.forwardRef((props, ref) => (
  <CustomScrollbars {...props} forwardedRef={ref} />
));

// ...

<FixedSizeList
  outerElementType={CustomScrollbarsVirtualList}
  {...rest}
/>

예 https://codesandbox.io/s/vmr1l0p463

outerElementType λ˜λŠ” innerElementType μ‚¬μš©ν•˜μ—¬ μ–Όλ§ˆλ‚˜ λ§Žμ€ κ³ κΈ‰ κΈ°λŠ₯을 μ‚¬μš©ν•  수 μžˆλŠ”μ§€ 정말 μ’‹μ•„ν•©λ‹ˆλ‹€.

λ°˜μ‘ μ°½ ν•˜λ‹¨μ˜ 슀크둀 μœ„μΉ˜λ₯Ό κ°μ§€ν•˜λ €κ³ ν•©λ‹ˆλ‹€.
κ°€λŠ₯ν• κΉŒμš”? 그것에 λŒ€ν•œ 아이디어가 μžˆμŠ΅λ‹ˆκΉŒ? codesandbox 예제λ₯Ό κ°–κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

μ‚¬μš© κ°€λŠ₯ν•œ ref propsλ₯Ό μ‚¬μš©ν•˜μ—¬ scrollHeight @rufoot λͺ©λ‘μ„ μš”μ²­ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ‚˜λŠ” μ†Œν’ˆμ—μ„œ scrollHeight 을 μ‚¬μš©ν•˜λ €κ³ ν–ˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ λ‚˜λŠ” 그것에 scrollHeight 속성이 μ—†λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.
@bvaughn 그것에 λŒ€ν•΄ μ–΄λ–€ 생각이 μžˆμŠ΅λ‹ˆκΉŒ?

https://codesandbox.io/s/github/bvaughn/react-window/tree/master/website/sandboxes/scrolling-to-a-list-item

scrollToRow200Auto = () => { this.listRef.current.scrollToItem(200); console.log("current position = ", this.listRef.current.props.scrollHeight) };

ν˜„μž¬ μœ„μΉ˜ = μ •μ˜λ˜μ§€ μ•ŠμŒ

@rufoot λ­”κ°€ https://codesandbox.io/s/4zjwwq98j4 ?

https://codesandbox.io/embed/jzo2lool2y

λ°˜μ‘ μ°½ ν•˜λ‹¨μ—μ„œ μ•„λž˜λ‘œ μŠ€ν¬λ‘€ν•˜λ©΄ ν•˜λ‚˜μ˜ κ²½κ³ λ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

@piecyk outerElementType μ†”λ£¨μ…˜μ„ μ‹œλ„ν–ˆμ§€λ§Œ 맀우 λŠλ¦½λ‹ˆλ‹€.

react-scrollbars-custom μ‹œλ„ν–ˆμŠ΅λ‹ˆλ‹€. 덜 λŠλ¦¬μ§€ 만 μ—¬μ „νžˆ λŠλ¦½λ‹ˆλ‹€. λˆ„κ΅°κ°€ μ‚¬μš©μž 지정 슀크둀 λ§‰λŒ€λ₯Ό μ‚¬μš©ν•˜μ—¬ 지연에 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆκΉŒ?

@ jancama2 λŠ” 그것을 λ°°ν‹€

@rufoot λ­”κ°€ https://codesandbox.io/s/4zjwwq98j4 ?

κ΅¬ν˜„μ„ μ‚¬μš©ν•˜κ³  μžˆμ§€λ§Œ forwardedRefκ°€ ν•¨μˆ˜κ°€ μ•„λ‹ˆλΌλŠ” 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

λ‚΄κ°€ ν•΄κ²°ν•˜λ €λŠ” μ•±μ˜ λ¬Έμ œλŠ” ν•­λͺ© λͺ©λ‘μ΄ 많고 ν•­λͺ©μ„ ν΄λ¦­ν•˜λ©΄ 앱이 λ‹€λ₯Έ 경둜둜 λ¦¬λ””λ ‰μ…˜λ˜λ―€λ‘œ 슀크둀 μœ„μΉ˜ (μ•„λ§ˆλ„ reduxμ—μ„œ)λ₯Ό μΆ”μ ν•΄μ•Όν•©λ‹ˆλ‹€. 그런 λ‹€μŒ 경둜 λ³€κ²½ ν›„ 슀크둀 μœ„μΉ˜λ₯Ό μ„€μ •ν•˜μ‹­μ‹œμ˜€.

@piecyk λ₯Ό react-window-infinite-loader 의 InfiniteLoader와 κ²°ν•© ν•΄ λ³΄μ…¨λ‚˜μš” ?
react-scrollbars-custom ν•˜κ³  있으며 λ¬΄ν•œ λ‘œλ”κ°€ κΉ¨μ§€λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.

λ‚΄ μ½”λ“œ :

<InfiniteLoader isItemLoaded={isItemLoaded} itemCount={items.total} loadMoreItems={loadMoreItems}>
      {({
        onItemsRendered,
        ref,
      }: {
        onItemsRendered: (props: ListOnItemsRenderedProps) => any;
        ref: React.Ref<any>;
      }) => (
        <List
          height={TABLE_HEIGHT}
          width={width}
          itemCount={items.total}
          itemSize={ROW_HEIGHT}
          onItemsRendered={onItemsRendered}
          itemData={{ items }}
          ref={ref}
          outerElementType={Scrollbar}
        >
          {Row}
        </List>
      )}
    </InfiniteLoader>

μ—…λ°μ΄νŠΈ : λ¬΄ν•œ 슀크둀 ꡬ성 μš”μ†Œμ™€ 관련이 μžˆλ‹€κ³  μƒκ°ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ‚¬μš©μž μ •μ˜ μŠ€ν¬λ‘€λ°”μ—μ„œ μž‘λ™ν•˜λ„λ‘ ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

λˆ„κ΅°κ°€κ°€ react-scrollbars-custom κ΅¬ν˜„μ„ λ‚˜μ™€ 곡유 ν•  수 μžˆλ‹€λ©΄ κ°μ‚¬ν•˜κ² μŠ΅λ‹ˆλ‹€.

@ranihorev κ·Έ νŒ¨ν‚€μ§€λ₯Ό μ‚¬μš©ν•΄μ•Όν•©λ‹ˆκΉŒ? μœ„μ—μ„œ 곡유 ν•œ μ½”λ“œ 펜 @piecyk λŠ” react-custom-scrollbarsλ₯Ό μ‚¬μš©ν•˜λ©° 잘 μž‘λ™ν•©λ‹ˆλ‹€ (refλ₯Ό 생성 ν•  λ•Œ μ˜ˆμ™Έ, μ–΄λ–€ 이유둜 λ‚΄ μ½”λ“œμ—μ„œ null 인 경우)

μ•Œκ² μŠ΅λ‹ˆλ‹€. λ‹€μ‹œ λ¬»κ² μŠ΅λ‹ˆλ‹€. @piecyk μœ„μ˜ μ½”λ“œ μƒ˜ν”Œμ„ μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€ ( @simjes에 λ‹΅μž₯ ν•œ
<TreeRoot onDragOver={e => this.onDragOver(e)} > <AutoSizer> {({ height, width }) => ( <List treeRef={this.props.treeRef} width={width} height={height} itemSize={index => rowHeights[index]} itemCount={nodeTree.length} itemData={{ nodeTree, expandedNodes, nodesFetching, nodesFetchingFailed, selectedNode, selectedNodeId, resetRowHeight: this.resetRowHeight, }} outerElementType={TreeScrollbar} outerRef={this.props.outerRef} onScroll={({ scrollOffset, scrollUpdateWasRequested }) => { if (scrollUpdateWasRequested) { console.log('scrollOffset: ', scrollOffset); } }} > {Node} </List> )} </AutoSizer> </TreeRoot>

CustomScrollbars 및 CustomScrollbarsVirtualListλ₯Ό μ‚¬μš©μžμ™€ λ™μΌν•˜κ²Œ κ΅¬ν˜„ν•˜μ§€λ§Œ refλŠ” 항상 nullμž…λ‹ˆλ‹€. AutoSizer와 λΆ€λͺ¨λ₯Ό μ‚¬μš©ν•˜λŠ” ꡬ성 μš”μ†Œμ—μ„œ refλ₯Ό λ§Œλ“€λ €κ³  μ‹œλ„ν–ˆμ§€λ§Œ 항상 nullμž…λ‹ˆλ‹€. 이유λ₯Ό μ΄ν•΄ν•˜λŠ” 데 도움을 μ£Όμ‹œλ©΄ κ°μ‚¬ν•˜κ² μŠ΅λ‹ˆλ‹€. μœ„μ—μ„œ μ–ΈκΈ‰ν–ˆλ“―μ΄ 슀크둀 μœ„μΉ˜λ₯Ό μΆ”μ ν•˜κ³  λͺ©λ‘μ΄ 맨 μœ„λ‘œ μ΄λ™ν•˜μ§€ μ•Šλ„λ‘ λ‚΄ μ•±μ˜ 경둜 변경에 μ„€μ •ν•  수 μžˆμ–΄μ•Όν•©λ‹ˆλ‹€.

@ChristopherHButler 이미 λ‚΄ μ½”λ“œμ—μ„œ ν•΄λ‹Ή νŒ¨ν‚€μ§€λ₯Ό μ—¬λŸ¬ 번 μ‚¬μš©ν•˜κ³  μžˆμœΌλ―€λ‘œ λ™μΌν•œ νŒ¨ν‚€μ§€λ₯Ό 계속 μ‚¬μš©ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€. I μ†”λ£¨μ…˜μ€ 맀우 μœ μ‚¬ν•˜μ§€λ§Œ μƒˆ 데이터λ₯Ό ptoperly κ°€μ Έ μ˜€μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

@ChristopherHButler λŠ” 문제의 μ½”λ“œ μƒŒλ“œ λ°•μŠ€ 예제 μ—†μ΄λŠ” λ§ν•˜κΈ°κ°€ 정말 μ–΄λ ΅μŠ΅λ‹ˆλ‹€. 무언가λ₯Ό 곡유 ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?
μ—¬κΈ°μ„œ κΈ°λ³Έ μ•„μ΄λ””μ–΄λŠ” react-custom-scrollbarsμ—μ„œ refλ₯Ό μ„€μ •ν•˜μ—¬ react-windowκ°€

AutoSizer λ˜λŠ” VariableSizeListλŠ”μ΄ μ˜ˆμ œμ—μ„œμ™€ 같이이 μ ‘κ·Ό λ°©μ‹μœΌλ‘œ μž‘λ™ν•©λ‹ˆλ‹€.
https://codesandbox.io/s/react-window-custom-scrollbars-t4352

@ranihorev μ½”λ“œ μƒŒλ“œ λ°•μŠ€ μ˜ˆμ œλ„ 곡유 ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

@piecyk κ°„λ‹¨ν•œ (그리고 깨진) 예제λ₯Ό λ§Œλ“­λ‹ˆλ‹€.
https://codesandbox.io/s/bvaughnreact-window-fixed-size-list-vertical-64kzh?fontsize=14

λ‚˜λŠ” λ˜ν•œ λ‹€λ₯Έ λ³€ν˜•μ„ μ‹œλ„ν–ˆμ§€λ§Œ (예 : μ°Έμ‘°λ₯Ό 슀크둀러 래퍼둜 μ„€μ •) μ„±κ³΅ν•˜μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€ ...

감사!

@ranihorev 이 μ ‘κ·Ό 방식은 μ‚¬μš©μž 지정 슀크둀 κ΅¬ν˜„μ— 관계없이 λ™μΌν•©λ‹ˆλ‹€. μŠ€ν¬λ‘€μ„ λ‹΄λ‹Ήν•˜λŠ” λ™μΌν•œ μš”μ†Œμ— λŒ€ν•œ μ°Έμ‘°λ₯Ό μ„€μ •ν•˜κ³  ν•΄λ‹Ή 슀크둀 이벀트λ₯Ό μ²˜λ¦¬ν•΄μ•Όν•©λ‹ˆλ‹€.

react-scrollbars-custom λŠ” λ Œλ”λ§ μ†Œν’ˆ νŒ¨ν„΄μ„ μ‚¬μš©ν•˜μ—¬ 더 쒋은 APIλ₯Ό μ œκ³΅ν•˜λ―€λ‘œ https://codesandbox.io/s/bvaughnreact-window-react-scrollbars-custom-pjyxs 와 같은 μž‘μ—…μ„ μˆ˜ν–‰ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ν”„λ‘œνŒŒμΌ λ§μ„ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. 도움이 λ˜μ—ˆκΈ°λ₯Ό λ°”λžλ‹ˆλ‹€.

@piecyk μ—¬κΈ°μ—μ„œ 데λͺ¨ μž‘μ—…μ„ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€ : https://codesandbox.io/s/4zjwwq98j4 . 슀크둀 μœ„μΉ˜λ₯Ό μ„€μ •ν•  수 μžˆλ„λ‘ onScrollStop을 μ‚¬μš©ν•˜μ—¬ reduxμ—μ„œ μž‘μ—…μ„ μ „λ‹¬ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€ (이 μŠ€λ ˆλ“œμ˜ 아이디어 : https://github.com/malte-wessel/react-custom-scrollbars/issues/146 μ΄μ§€λ§Œ onScrollStart 및 onScrollStop이 λ‚΄ μ½”λ“œ λ‚˜ 데λͺ¨μ—μ„œ μž‘λ™ν•˜μ§€ μ•ŠλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. κ·Έ 이유λ₯Ό μ•Œκ³  μžˆμŠ΅λ‹ˆκΉŒ? λͺ©λ‘μ—μ„œ μŠ€ν¬λ‘€λ°”λ‘œ μ†Œν’ˆμ„ 전달할 μˆ˜μžˆλŠ” 방법이 μžˆμŠ΅λ‹ˆκΉŒ?

@ChristopherHButler μ΅œμ„ μ˜ 선택은 μ»¨ν…μŠ€νŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ μ†Œν’ˆμ„ μ „λ‹¬ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

https://codesandbox.io/s/bvaughnreact-window-fixed-size-list-vertical-v2-usi1m

--- νŽΈμ§‘ 됨
κ²½λ‘œκ°€ λ³€κ²½ 될 λ•Œ 전체 λͺ©λ‘μ„ 마운트 ν•΄μ œν•˜λ©΄ μž‘μ—…μ„ 전달할 수 μžˆμŠ΅λ‹ˆλ‹€. Last scrollOffset은 ref에 μ €μž₯되고 VariableSizeList의 onScroll: function λ₯Ό μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  슀크둀 λ³€κ²½μ‹œ μ—…λ°μ΄νŠΈ 될 수 μžˆμŠ΅λ‹ˆλ‹€. 그러면 μ†Œν’ˆμ„ Scrollbars에 전달할 ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€.

@piecyk ꡉμž₯ν•©λ‹ˆλ‹€, κ°μ‚¬ν•©λ‹ˆλ‹€!
btw, ν•„μš”ν•œ 것은 onScroll ν•¨μˆ˜ (λ‚΄κ°€ λ†“μΉœ) 뿐이고 refλ₯Ό 전달할 ν•„μš”κ°€ μ „ν˜€μ—†λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.
https://codesandbox.io/s/bvaughnreact-window-react-scrollbars-custom-99dn1

@piecyk μ£„μ†‘ν•©λ‹ˆλ‹€. VariableSizeList의 κ΅¬ν˜„μ΄ AutoSizer에 λž˜ν•‘λ˜μ–΄ 있고이λ₯Ό λ Œλ”λ§ν•˜λŠ” ꡬ성 μš”μ†ŒλŠ” 클래슀 기반 ꡬ성 μš”μ†Œμ΄λ―€λ‘œ μ»¨ν…μŠ€νŠΈλ₯Ό μ‚¬μš©ν•  수 μžˆλŠ”μ§€ ν™•μ‹€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 이것이 λ‚΄κ°€ onScrollStop을 μž‘λ™μ‹œν‚¬ μˆ˜μ—†λŠ” μ΄μœ μΌκΉŒμš”?

λΉ λ₯Έ μ—…λ°μ΄νŠΈ:
ꡬ성 μš”μ†Œ μƒνƒœλ₯Ό μΆ”κ°€ν•˜κ³  onScroll둜 μ„€μ •ν–ˆμŠ΅λ‹ˆλ‹€.

`
class BaseTree extends Component {
...
μƒνƒœ = {scrollPosition : 0,};
...
listRef = React.createRef ();
outerRef = React.createRef ();
...
render {
const {λ…Έλ“œ, nodesFetching, nodesFetchingFailed, extendedNodes, selectedNode} = this.props;
λ°˜ν™˜ (

{({높이, λ„ˆλΉ„}) => (
ref = {this.listRef}
className = "λͺ©λ‘"
outerRef = {this.outerRef}
outerElementType = {TreeScrollbar}
λ„ˆλΉ„ = {λ„ˆλΉ„}
높이 = {높이}
onScroll = {({scrollOffset}) => this.setState ({scrollPosition : scrollOffset})}
itemSize = {index => rowHeights [index]}
itemCount = {nodeTree.length}
itemData = {{
nodeTree,
extendedNodes,
nodesFetching,
nodesFetchingFailed,
selectedNode,
selectedNodeId,
resetRowHeight : this.resetRowHeight,
}}
>
{λ§ˆλ””}

)}

);
}}

const mapStateToProps = μƒνƒœ => ({
scrollPosition : selectors.getTreeScrollPosition (state),
});

const mapDispatchToProps = dispatch => ({
setTreeScrollPosition : position => dispatch (actions.setTreeScrollPosition ({position})),
});

κΈ°λ³Έ μ—°κ²° 내보내기 (mapStateToProps, mapDispatchToProps) (BaseTree);
`

그런 λ‹€μŒ componentWillUnmoutμ—μ„œ λ‹€μŒκ³Ό 같이 reduxμ—μ„œ μœ„μΉ˜λ₯Ό μ„€μ •ν•˜λŠ” μž‘μ—…μ„ μ „λ‹¬ν•©λ‹ˆλ‹€.

componentWillUnmount() { this.props.setTreeScrollPosition(this.state.scrollPosition); }

λ‚΄ μœ μΌν•œ λ¬Έμ œλŠ” ꡬ성 μš”μ†Œκ°€ λ‹€μ‹œ μž₯μ°© 될 λ•Œ 슀크둀 μœ„μΉ˜λ₯Ό μ„€μ •ν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. λ‹€μŒκ³Ό 같이 this.listRefμ—μ„œ scrollTop λ©”μ„œλ“œμ— μ•‘μ„ΈμŠ€ ν•΄ λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

this.listRef.current.scrollTop() ν•˜μ§€λ§Œ ν•¨μˆ˜κ°€ μ•„λ‹ˆλΌλŠ” 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€. 슀크둀 μœ„μΉ˜λ₯Ό μ„€μ •ν•˜λŠ” 데 μ‚¬μš©ν•  μˆ˜μžˆλŠ” 속성 (this.listRef λ˜λŠ” this.outerRef)을 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€. λ‹€μŒκ³Ό 같이 BaseTree의 componentDidMountμ—μ„œ μ„€μ •ν•  수 μžˆλ‹€κ³  μƒκ°ν–ˆμŠ΅λ‹ˆλ‹€.
componentDidMount() { const { scrollPosition } = this.props; if (this.listRef.current) { // console.log('initializing scroll position to : ', scrollPosition); this.listRef.current.scrollTop(scrollPosition); } }
이 μž‘μ—…μ— 도움을 μ£Όμ‹œλ©΄ λŒ€λ‹¨νžˆ κ°μ‚¬ν•˜κ² μŠ΅λ‹ˆλ‹€!
νŽΈμ§‘ : λ―Έμ•ˆν•˜μ§€λ§Œ λ‚΄ μ½”λ“œκ°€μ΄ νŽΈμ§‘κΈ°μ—μ„œ μ˜¬λ°”λ₯΄κ²Œ μ„œμ‹μ„ μ§€μ •ν•˜μ§€ μ•ŠλŠ” 것 κ°™μ•„μ„œ μ‚¬κ³Όλ“œλ¦½λ‹ˆλ‹€.

@ranihorev forward ref λ°˜μ‘ 창에 scrollTo, scrollToItem 같은 κΈ°λŠ₯이 μž‘λ™ν•΄μ•Όν•©λ‹ˆλ‹€.

@ChristopherHButler μ»¨ν…μŠ€νŠΈλŠ” λ¬Έμ„œμ—μ„œ λΉŒλ“œ λœλŒ€λ‘œ μ •ν™•ν•˜κ²Œ μž‘λ™ν•΄μ•Όν•©λ‹ˆλ‹€.

μ»¨ν…μŠ€νŠΈλŠ” λͺ¨λ“  λ ˆλ²¨μ—μ„œ μˆ˜λ™μœΌλ‘œ μ†Œν’ˆμ„ 전달할 ν•„μš”μ—†μ΄ ꡬ성 μš”μ†Œ 트리λ₯Ό 톡해 데이터λ₯Ό 전달할 μˆ˜μžˆλŠ” 방법을 μ œκ³΅ν•©λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ μ˜ˆμ „μ— μ–ΈκΈ‰ν–ˆλ“―μ΄ 경둜 λ³€κ²½μ‹œ 전체 ꡬ성 μš”μ†Œλ₯Ό 마운트 ν•΄μ œν•˜λ©΄ μ†Œν’ˆμ„ 전달할 ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. 슀크둀이 λ°œμƒν•˜λŠ” λ™μ•ˆ ν•„μš”ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μƒνƒœμ— scrollPosition λ₯Ό μ €μž₯ν•˜μ§€ μ•Šκ³ , λ‹€μ‹œ λ Œλ”λ§ν•˜μ§€ μ•Šκ³  ref에 μ €μž₯ν•©λ‹ˆλ‹€.

onScroll={({ scrollOffset }) => this.setState({ scrollPosition: scrollOffset })}

// to 

lastScrollOffsetRef = React.createRef(0);

<List
  onScroll={({ scrollOffset }) => {
    this.lastScrollOffsetRef.current = scrollOffset
  }}
  // ...rest
/>

// then in 
componentWillUnmount() { 
  this.props.setTreeScrollPosition(this.lastScrollOffsetRef.current); 
}

outerRef 에 κ΄€ν•΄μ„œλŠ” κ·€ν•˜μ˜ κ²½μš°μ—λŠ” ν•„μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. listRef.current.scrollTo λŠ” μ‚¬μš©ν•˜λ €λŠ” μ˜¬λ°”λ₯Έ λ°©λ²•μž…λ‹ˆλ‹€. componentDidMount μ—μ„œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” 아이디어가 μ •ν™•ν•˜κ³  μž‘λ™ν•΄μ•Όν•©λ‹ˆλ‹€.

https://codesandbox.io/s/bvaughnreact-window-fixed-size-list-vertical-80zo7

refsλ₯Ό μ„€μ •ν•˜λŠ” λ™μ•ˆ 타이밍 문제처럼 λ³΄μž…λ‹ˆλ‹€. AutoSizerκ°€ this.listRef.currentλ₯Ό μ •μ˜λ˜μ§€ μ•Šκ²Œ λ§Œλ“œλŠ” List λ Œλ”λ§μ„ μ§€μ—°μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

hacky μ˜΅μ…˜μ€ setTimeout으둜 λ°˜μ‘ 라이프 사이클을 μ€‘λ‹¨ν•˜κ³  λ‹€μŒ ν‹±μ—μ„œ refλ₯Ό ν˜ΈμΆœν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

componentDidMount() {
  window.setTimeout(() => {
    if (this.listRef.current) {
      this.listRef.current.scrollTo(this.props.scrollPosition);
    }
  }, 0);
}

@piecyk 도움을 μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€, 정말 κ°μ‚¬ν•©λ‹ˆλ‹€ :)

κ°μ‚¬ν•©λ‹ˆλ‹€ @piecyk μž‘λ™ν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. 경둜 λ³€κ²½ ν›„ λ§ˆμš΄νŠΈμ— μ•½κ°„μ˜ κΉœλ°•μž„μ΄ μžˆμ§€λ§Œ ν•¨κ»˜ μ‚΄ 수 μžˆμŠ΅λ‹ˆλ‹€ :) λ˜ν•œ className을 μ‚¬μš©ν•˜μ—¬ scrollPosition을 μ „λ‹¬ν•˜κ³  CustomScrollbars의 refSetter에 scrollTop을 μ„€μ •ν•˜λŠ” 또 λ‹€λ₯Έ 해킹을 μ‹œλ„ν–ˆμŠ΅λ‹ˆλ‹€.
if (scrollbarsRef) { forwardedRef(scrollbarsRef.view); // HACK scrollbarsRef.scrollTop(className); }
잘 μž‘λ™ν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.
λͺ¨λ“  도움에 λ‹€μ‹œ ν•œλ²ˆ κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€. λŒ€λ‹¨νžˆ κ°μ‚¬ν•©λ‹ˆλ‹€ !! πŸ™ŒπŸ»

μ•ˆνƒ€κΉκ²Œλ„μ΄ 문제의 λͺ¨λ“  μ˜ˆμ œκ°€ μ œλŒ€λ‘œ μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€ (λ•Œλ‘œλŠ” λ§ˆμš°μŠ€κ°€ μŠ€ν¬λ‘€μ— μ‘λ‹΅ν•˜μ§€ μ•ŠμŒ).

κ·ΈλŸ¬λ‚˜μ΄ μ˜ˆμ œλŠ” μ™„λ²½ν•˜κ²Œ μž‘λ™ν•©λ‹ˆλ‹€!

@ranihorev 이 μ ‘κ·Ό 방식은 μ‚¬μš©μž 지정 슀크둀 κ΅¬ν˜„μ— 관계없이 λ™μΌν•©λ‹ˆλ‹€. μŠ€ν¬λ‘€μ„ λ‹΄λ‹Ήν•˜λŠ” λ™μΌν•œ μš”μ†Œμ— λŒ€ν•œ μ°Έμ‘°λ₯Ό μ„€μ •ν•˜κ³  ν•΄λ‹Ή 슀크둀 이벀트λ₯Ό μ²˜λ¦¬ν•΄μ•Όν•©λ‹ˆλ‹€.

react-scrollbars-custom λŠ” λ Œλ”λ§ μ†Œν’ˆ νŒ¨ν„΄μ„ μ‚¬μš©ν•˜μ—¬ 더 쒋은 APIλ₯Ό μ œκ³΅ν•˜λ―€λ‘œ https://codesandbox.io/s/bvaughnreact-window-react-scrollbars-custom-pjyxs 와 같은 μž‘μ—…μ„ μˆ˜ν–‰ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

react-scrollbars-custom μ‹œλ„ν–ˆμŠ΅λ‹ˆλ‹€. 덜 λŠλ¦¬μ§€ 만 μ—¬μ „νžˆ λŠλ¦½λ‹ˆλ‹€. λˆ„κ΅°κ°€ μ‚¬μš©μž 지정 슀크둀 λ§‰λŒ€λ₯Ό μ‚¬μš©ν•˜μ—¬ 지연에 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆκΉŒ?

ν•΄λƒˆμ–΄? μ΅œμ’… 해결책은 λ¬΄μ—‡μž…λ‹ˆκΉŒ?

이것이 λˆ„κ΅¬μ—κ²Œλ‚˜ λ„μ›€μ΄λœλ‹€λ©΄ OverlayScrollbars 와 ν•¨κ»˜ μž‘λ™ν•˜λ„λ‘ κ΄€λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€. 슀크둀 이벀트λ₯Ό ν•΄λ‹Ή μš”μ†Œμ— μ „λ‹¬ν•˜κΈ° λ§Œν•˜λ©΄λ©λ‹ˆλ‹€. 방법은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

const Overflow = ({ children, onScroll }) => {
  const ofRef = useRef(null);

  useEffect(() => {
    const el = ofRef.current.osInstance().getElements().viewport;

    if (onScroll) el.addEventListener('scroll', onScroll);

    return () => {
      if (onScroll) el.removeEventListener('scroll', onScroll);
    };
  }, [onScroll]);

  return (
    <OverlayScrollbarsComponent
      options={options}
      ref={ofRef}
    >
      {children}
    </OverlayScrollbarsComponent>
  );
};

그런 λ‹€μŒ 가상화 된 ꡬ성 μš”μ†Œμ—μ„œ :

<FixedSizeGrid
  {...props}
   outerElementType={Overflow}
>

λ‚˜λŠ” 이것을 FixedSizeGrid 와 ν•¨κ»˜ μ‚¬μš©ν•˜κ³  μžˆμ§€λ§Œ λͺ©λ‘μ— λŒ€ν•΄μ„œλ„ λ™μΌν•˜κ²Œ μž‘λ™ν•©λ‹ˆλ‹€.

λ„μ›€μ΄λ˜κΈ°λ₯Ό λ°”λžλ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰