μλ¨μ κ³ μ λ κ³ μ ν€λκ° μλ 그리λλ₯Ό μμ±ν΄μΌ νλ μ¬μ© μ¬λ‘κ° μμ΅λλ€. react-virtualizedμμ μ΄κ²μ λ κ°μ 그리λ κ΅¬μ± μμ(νλλ ν€λμ©, νλλ 그리λ λ°λμ©)λ₯Ό μμ±νκ³ ν€λ 그리λμ μν μ€ν¬λ‘€μ΄ λ©μΈ 그리λμ λκΈ°νλλλ‘ μ€ν¬λ‘€ μμΉλ₯Ό λκΈ°ννμ¬ μνν μ μμ΅λλ€.
λ³λμ ν¨ν€μ§λ‘ μΆκ° κΈ°λ₯μ ꡬμΆνκΈ° μν΄ λ²λ€ ν¬κΈ°μ κ°λ μ 볡μ‘μ± μΈ‘λ©΄μμ λ°μ μ°½μ λ κ°λ³κ² μ μ§νλ €κ³ νλ€λ κ²μ μκ³ μμ΅λλ€. μ λ λμνλ λ°©ν₯μ λλ€. react-virtualizedμ ScrollSync κ΅¬μ± μμλ₯Ό μΆμΆνκ±°λ λ°μ μ°½μμ μλνλλ‘ μ‘°μ ν μ μλ€κ³ μκ°ν©λλ€. κ·Έλ¬λ κ·Έλ κ² νλ €λ©΄ ν€λ 그리λμ μ€ν¬λ‘€ μ€νμ μ μ§μ κ΄λ¦¬ν μ μλλ‘ react-windowκ° scrollLeft λ° scrollTopμ λν propsλ₯Ό μλ½ν΄μΌ ν©λλ€.
μ§μνκ³ μ νλ μ¬μ© μ¬λ‘μ λκΉ? κ·Έλ μ§ μλ€λ©΄ μ΄κ²μ μ§μ ꡬννκΈ° μν΄ μ΄λ€ λ°©ν₯μΌλ‘ κ°μΌνλμ§μ λν μ‘°μΈμ΄ μμ΅λκΉ?
μ΄ λΌμ΄λΈλ¬λ¦¬μμ μμ ν΄ μ£Όμ μ κ°μ¬ν©λλ€. λͺ λ λμ react-virtualizedλ₯Ό μ¬μ©ν΄ μ¨ μ¬λμΌλ‘μ, react-windowλ₯Ό μμνλ κ²μ΄ κ°λ¨νκ³ μλ κ°μ μμ΄ μΌλ§λ μ±λ₯μ΄ μ’μμ§ κ°μ¬ν©λλ€.
λ¨Όμ μ’μ λ§μκ³Ό κΈμ μ μΈ νΌλλ°±μ κ°μ¬λ립λλ€. μ§κΈκΉμ§ react-windowκ° μ μλνκ³ μλ€λ μμμ λ€μΌλ κΈ°μ©λλ€!
ScrollSyncμ κ°μ κ΅¬μ± μμκ° react-windowμ μμ‘΄νλ λ 립 μ€νν ν¨ν€μ§λ‘ μΆμλ μ μλ€λ μ μλ λμν©λλ€.
scroll propsμ λν κ·νμ νΉμ μ§λ¬Έκ³Ό κ΄λ ¨νμ¬ μ΄κ²μ react-virtualizedμ ν¨κ» μ¬μ©ν ν λͺ κ°μ§ μ¬κ°ν λ¨μ μ΄ μμμ κΉ¨λ¬μκΈ° λλ¬Έμ νλ‘μ νΈμ κΈ°κΊΌμ΄ μ μ©ν λ³κ²½ μ¬νμ΄ μλλλ€. κΆκΈν μ μ΄ μμΌλ©΄ React λΈλ‘κ·Έμ μ€μ λ‘ μ΄μ λν΄ μΌμ΅λλ€.
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#anti -pattern-erasing-state-when-props-change
μ μ¬ν λκΈ°ν λμμ λ¬μ±νκΈ° μν΄ react-windowκ° μ 곡νλ λͺ λ Ήν μ€ν¬λ‘€ APIλ₯Ό μ¬μ©ν μ μμ΅λλ€. μνμ μ λ¬νλ λμ μ»€λ° μλͺ μ£ΌκΈ°μμ μ΄λ¬ν λ©μλλ₯Ό νΈμΆνκΈ°λ§ νλ©΄ λ©λλ€.
μ΄κ²μ΄ μλ―Έκ° μκΈ°λ₯Ό λ°λΌμ§λ§ κ·Έλ μ§ μμ κ²½μ° νμ μ§λ¬Έμ μμ λ‘κ² νμμμ€!
κ·Έκ²μ μμ ν μλ―Έκ° μμ΅λλ€. μ μ κ°μ¬ν©λλ€! λλ κ·Έκ²μ μλ μμΌ°κ³ μ€μ λ‘ μ€μ νκΈ°κ° λ§€μ° μ½μ΅λλ€. λ무 μ¬μμ λ 립 μ€νν ν¨ν€μ§λ₯Ό 보μ¦νμ§ μμ΅λλ€. λ¬Έμμ μμΌ μλ μμ§λ§ κ·Έκ² λΉμ μ μ νλΌκ³ μκ°ν©λλ€. λμ€μ λ€λ₯Έ μ¬λμ΄ μ΄ λ¬Έμ λ₯Ό λ°κ²¬ν κ²½μ°λ₯Ό λλΉνμ¬ μμ μ€μΈ Code Sandbox μμ μ λν λ§ν¬λ₯Ό μ¬κΈ°μ λ¨κΈΈ κ²μ λλ€.
https://codesandbox.io/s/y3pyp85zm1
TLDR - ν€λ 그리λμ refλ₯Ό λ£κ³ λ³Έλ¬Έ 그리λμ λ£μ΅λλ€.
onScroll={({ scrollLeft }) => this.headerGrid.current.scrollTo({ scrollLeft })}
λ§ν¬ μ£Όμ μ κ°μ¬ν©λλ€! λ§€μ° μ¬λ €κΉμ΅λλ€.
2018λ 11μ 8μΌ λͺ©μμΌ μ€ν 1:09 Reagan Keeler < [email protected] μμ±:
κ·Έκ²μ μμ ν μλ―Έκ° μμ΅λλ€. μ μ κ°μ¬ν©λλ€! λλ κ·Έκ²μ μλ μμΌ°κ³ ,
μ€μ λ‘ μ€μ νκΈ°κ° λ§€μ° μ½μ΅λλ€. λ무 μ¬μμ νμ€ν
λ 립ν ν¨ν€μ§λ₯Ό 보μ¦ν©λλ€. λ¬Έμμ μμΌ μλ μμ§λ§ κ·Έκ² λΉμ μ κ²μ λλ€.
μ ννλ κ² κ°μμ. μ¬κΈ°μ λ΄ μμ μ½λ μλλ°μ€ μμ μ λν λ§ν¬λ₯Ό λ¨κΈΈ κ²μ λλ€.
λ€λ₯Έ μ¬λμ΄ λ―Έλμ μ΄ λ¬Έμ λ₯Ό μ°μ°ν λ°κ²¬νλ κ²½μ°λ₯Ό λλΉνμ¬.https://codesandbox.io/s/y3pyp85zm1
TLDR - ν€λ 그리λμ refλ₯Ό λ£κ³ λ³Έλ¬Έ 그리λμ λ£μ΅λλ€.
onScroll={({ scrollLeft }) => this.headerGrid.current.scrollTo({ scrollLeft })}
β
μ΄κΈ°/λ«κΈ° μνλ₯Ό μμ νκΈ° λλ¬Έμ μ΄ λ©μμ§κ° νμλ©λλ€.
μ΄ μ΄λ©μΌμ μ§μ λ΅μ₯νκ³ GitHubμμ νμΈνμΈμ.
https://github.com/bvaughn/react-window/issues/86#issuecomment-437156749 ,
λλ μ€λ λ μμκ±°
https://github.com/notifications/unsubscribe-auth/AABznTUunzEIs6bVQfVsz7T21L2-Pkkoks5utJ17gaJpZM4YVMd7
.
μ΄κ²μ μ°μ°ν λ°κ²¬ν μ¬λμκ²λ react-virtualized
μ€ν¬λ‘€ λκΈ°νλ μλ¨/μ€λ₯Έμͺ½/νλ¨/μΌμͺ½ κ³ μ μνΌ κ·Έλ¦¬λκ° μμλλ° μ΄ libλ‘ λ§μ΄κ·Έλ μ΄μ
νμ΅λλ€. μμ μ루μ
μ΄ λ€λ₯Έ λΌμ΄λΈλ¬λ¦¬μμ ScrollSync
λ₯Ό μ¬μ©νλ κ²λ³΄λ€ λ λ«μ§ μλλΌλ μ΅μν μ±λ₯μ΄ λ°μ΄λκ³ κ³ ν΅μ΄ λνλ€κ³ λ§ν κ²μ
λλ€.
λν μλ‘μ΄ useRef
λ°μ νν¬(https://reactjs.org/docs/hooks-reference.html#useref)μλ μμ£Ό μ μ΄μΈλ¦½λλ€.
const topRef = useRef();
const rightRef = useRef();
const bottomRef = useRef();
const leftRef = useRef();
...
<Grid
onScroll={({ scrollLeft, scrollTop }) => {
if (leftRef.current) {
leftRef.current.scrollTo({ scrollTop });
}
if (rightRef.current) {
rightRef.current.scrollTo({ scrollTop });
}
if (topRef.current) {
topRef.current.scrollTo({ scrollLeft });
}
if (bottomRef.current) {
bottomRef.current.scrollTo({ scrollLeft });
}
}}
...
/>
λ©μ§! @ranneydλ₯Ό 곡μ ν΄ μ£Όμ μ κ°μ¬ν©λλ€!
λν μλ‘μ΄
useRef
λ°μ νν¬(https://reactjs.org/docs/hooks-reference.html#useref)μλ μμ£Ό μ μ΄μΈλ¦½λλ€.
@ranneyd κ°μ¬ν©λλ€
μ€μ μ¬λ‘λ₯Ό 곡μ ν μ μμ΅λκΉ?
@ranneyd λ€μ ν λ² κ°μ¬λ립λλ€. κ·νμ μ κ·Ό λ°©μμ λ°λκ³ μ€ν¬λ‘€ λκΈ°νκ°
μ€ν¬λ‘€λ°μ μ¨κ²¨μ§ μ€λ²νλ‘λ 그리λ λ κ·Όμ²μμ μ λ ¬ λΆλμ μΌμΌν΅λλ€.
μ΄ λ¬Έμ λ₯Ό ν΄κ²°νλ λ°©λ²μ λν μ μ μ¬νμ΄ μμ΅λκΉ?
미리 κ°μ¬λ립λλ€
@carlosagsmendes μ€ν¬λ‘€ λ§λ λλ¬Έμ λλ€. μΌμͺ½μμ λμ΄μμ μ€ν¬λ‘€ λ§λ ν¬κΈ°λ₯Ό λΊ λμ΄λ₯Ό λ§λλλ€. μ₯μΉ κ°μ μΌκ΄μ±μ μ μ§νκΈ° μν΄ CSSλ₯Ό μ¬μ©νμ¬ μ€ν¬λ‘€ λ§λ ν¬κΈ°λ₯Ό μλμΌλ‘ νλ μ½λ©ν©λλ€. μ½ν μΈ κ° λ무 λμ μ΄μ΄μ μ€ν¬λ‘€ λ§λκ° μμ μλ μκ³ μμ μλ μλ κ²½μ° "νλͺ© μ * νλͺ© ν¬κΈ° < λλΉ(λͺ¨λ κ°μ΄ λ°λ‘ μ¬κΈ°μ μμ΄μΌ ν¨)"μ κ°μ μμ μ μνν λ€μ κ·Έμ λ°λΌ λμ΄λ₯Ό λ³κ²½ν©λλ€.
μ₯μΉ κ°μ μΌκ΄μ±μ μ μ§νκΈ° μν΄ CSSλ₯Ό μ¬μ©νμ¬ μ€ν¬λ‘€ λ§λ ν¬κΈ°λ₯Ό μλμΌλ‘ νλ μ½λ©ν©λλ€.
FWIW dom-helpers ν¨ν€μ§μλ νμ¬ μ₯μΉμ λλΉλ₯Ό μλ €μ£Όλ νΈλ¦¬ν scrollbarSize
κΈ°λ₯ μ΄ μμ΅λλ€. νλ μ½λ©λ³΄λ€ λμ μ μμ΅λλ€.
@bvaughn λ€! λλ κ·Έκ²μ μΈκΈνλ κ²μ μμλ€. κ·Έλ¬λ κ·Έκ²μ μ°λ¦¬μκ² ν¨κ³Όκ° μμμ΅λλ€. λ΄ μκ°μ λ¬Έμ λ μ°λ¦¬κ° μ΄λ―Έ νλ μ½λ©λ μ€ν¬λ‘€ λ°λ₯Ό νκ³ μμκ³ κ·Έκ²μ΄ νΌλμ€λ¬μ λ€λ κ²μ λλ€.
μ κ°μ¬ν©λλ€. λλ κ·Έκ²μ μλ ν κ²μ΄λ€!
μν VariableSizeListμμ μλν©λκΉ? μλνμ§λ§ λΈλΌμ°μ κ° λ©μΆ₯λλ€.
onScroll={({ scrollLeft }) => this.headerGrid.current.scrollTo({ scrollLeft })}
VariableSizeGrid μ μ μλνμ§λ§ μ€ν¬λ‘€ μ ν€λκ° μ½κ° λ€μ²μ§λλ€.
@ajaymore λ ν€λ μ§μ°μ΄ μμΌλ―λ‘ Macμμ μ€ν¬λ‘€ ν μ μ¬μ©ν λ μ€ν¬λ‘€ λκΈ°ν λ¬Έμ κ° λ°μν©λλ€. MacOSXμλ μ€ν¬λ‘€μ "λΆλλ½κ²" λ§λ€κΈ° μν΄ λ³΄κ°νλ μμ° μ€ν¬λ‘€ κΈ°λ₯μ΄ λ΄μ₯λμ΄ μμ΅λλ€. μλ‘ κ³ μΉ¨ λΉλλ μ€μ λ‘ Chromeμ μ λλ©μ΄μ νλ μ μλλ³΄λ€ λΉ λ¦ λλ€. λ°λΌμ μ€ν¬λ‘€νλ μμλ V8/ScrollSyncκ° DOMμ μ λ°μ΄νΈν μκ°μ κ°κΈ° μ μ μ λλ©μ΄μ λ©λλ€. μ΄κ²μ λ΄κ° λ³Έ μ μ΄ μλ κΈ°μ μ νκ³μ λλ€.
μ¬λ―Έμλ μ¬μ€: λΈλΌμ°μ μμ μ€ν¬λ‘€ λ§λλ₯Ό μλμΌλ‘ μ¬μ©νλ©΄(μ: μμ κ²μ λμ΄μ ꡬμ λ°©μμΌλ‘ μ€ν¬λ‘€νλ κ²κ³Ό κ°μ΄) μμ ν μ μλν©λλ€. λ³΄κ° κΈ°λ₯μ μ€ν¬λ‘€ ν /νΈλ ν¨λ μ€μμ΄νμ λ΄μ₯λμ΄ μμ΅λλ€.
@ajaymore λ ν€λ μ§μ°μ΄ μμΌλ―λ‘ Macμμ μ€ν¬λ‘€ ν μ μ¬μ©ν λ μ€ν¬λ‘€ λκΈ°ν λ¬Έμ κ° λ°μν©λλ€. MacOSXμλ μ€ν¬λ‘€μ "λΆλλ½κ²" λ§λ€κΈ° μν΄ λ³΄κ°νλ μμ° μ€ν¬λ‘€ κΈ°λ₯μ΄ λ΄μ₯λμ΄ μμ΅λλ€. μλ‘ κ³ μΉ¨ λΉλλ μ€μ λ‘ Chromeμ μ λλ©μ΄μ νλ μ μλλ³΄λ€ λΉ λ¦ λλ€. λ°λΌμ μ€ν¬λ‘€νλ μμλ V8/ScrollSyncκ° DOMμ μ λ°μ΄νΈν μκ°μ κ°κΈ° μ μ μ λλ©μ΄μ λ©λλ€. μ΄κ²μ λ΄κ° λ³Έ μ μ΄ μλ κΈ°μ μ νκ³μ λλ€.
μ¬λ―Έμλ μ¬μ€: λΈλΌμ°μ μμ μ€ν¬λ‘€ λ§λλ₯Ό μλμΌλ‘ μ¬μ©νλ©΄(μ: μμ κ²μ λμ΄μ ꡬμ λ°©μμΌλ‘ μ€ν¬λ‘€νλ κ²κ³Ό κ°μ΄) μμ ν μ μλν©λλ€. λ³΄κ° κΈ°λ₯μ μ€ν¬λ‘€ ν /νΈλ ν¨λ μ€μμ΄νμ λ΄μ₯λμ΄ μμ΅λλ€.
@ranneyd λΉ λ₯Έ λ΅λ³ κ°μ¬ν©λλ€. νκ³λΌλ μ μ λμν©λλ€. λλΆλΆμ μ₯μΉμμ μ μλνλ―λ‘ ν° λ¬Έμ λ μλλλ€.
@bvaughn position: sticky
κ°μ§κ³ λμλ³Έ μ μλμ? νλμ μμ¨λ΄μ λΈλΌμ°μ μ§μμ΄ λ―Έμ½νκ±Έλ‘ μλλ°, μ§μλλ λΈλΌμ°μ μμ νμ©ν μ μλ λ°©λ²μ΄ μμκΉμ...
@ajaymore μ λμΌν λ¬Έμ κ° μμ΅λλ€. μ€λͺ ν λλ‘ μλ μ€ν¬λ‘€μμλ μ λλ‘ μλν¨). PCμμ ChromeμΌλ‘ ν μ€νΈ μ€μ΄λ―λ‘ Macλ§μ λ¬Έμ λ μλ κ² κ°μ΅λλ€... λκ΅°κ° μ΄ λ¬Έμ λ₯Ό ν΄κ²°νλ λ° μ±κ³΅νμ΅λκΉ?
@alonrbar Windows PCμμλ λμΌν λ¬Έμ κ° μμ΅λλ€.
μ€μ λ‘ μ μκ² λ§λ ν΄κ²° λ°©λ²μ μ°Ύμμ΅λλ€.
μΌλ°μ μΈ μμ΄λμ΄λ μλ 그리λμ μ¨μ΄ onScroll μ΄λ²€νΈλ₯Ό νμΉλ "κ·Έλ¦Όμ 그리λ"λ₯Ό λ§λ λ€μ μ΄λ₯Ό μ¬μ©νμ¬ μλ 그리λμ νμν λ€λ₯Έ 그리λλ₯Ό μλμΌλ‘ μ€ν¬λ‘€νλ κ²μ
λλ€. μ±λ₯μ΄ μ½κ° λλ €μ§μ§λ§ λͺ¨λ 그리λκ° μ λκΈ°νλλλ‘ μ μ§νλ―λ‘ νΈλ μ΄λ μ€νλ₯Ό κ³ λ €ν΄μΌ ν©λλ€.
μ½λλ λ€μκ³Ό κ°μ΅λλ€.
import styled from '@emotion/styled';
import * as React from 'react';
import { VariableSizeGrid, VariableSizeGridProps } from 'react-window';
import { SizeUtils } from '../utils';
export interface SyncableGridProps extends VariableSizeGridProps {
mainGridRef: React.Ref<VariableSizeGrid>;
shadowGridRef: React.Ref<VariableSizeGrid>;
hideVerticalScrollbar?: boolean;
}
export class SyncableGrid extends React.PureComponent<SyncableGridProps> {
public render() {
const { height, width } = this.props;
const {
onScroll,
mainGridRef: mainGridRef1,
shadowGridRef: shadowGridRef1,
...mainProps
} = this.props;
const {
children,
style,
overscanRowsCount,
overscanColumnsCount,
overscanCount,
useIsScrolling,
onItemsRendered,
mainGridRef: mainGridRef2,
shadowGridRef: shadowGridRef2,
innerRef,
outerRef,
...shadowProps
} = this.props;
return (
<SyncWrapper
style={{
height,
width
}}
>
<MainGrid
{...mainProps}
style={Object.assign({}, style, {
overflowY: 'scroll'
})}
ref={mainGridRef1}
/>
<GridShadow
{...shadowProps}
style={{
position: 'absolute',
top: 0,
left: 0
}}
ref={shadowGridRef1}
>
{() => null}
</GridShadow>
</SyncWrapper>
);
}
}
// ---------------- //
// styles //
// ---------------- //
const SyncWrapper = styled.div`
position: relative;
overflow: hidden;
`;
export interface MainGridProps extends VariableSizeGridProps {
hideVerticalScrollbar?: boolean;
}
export const MainGrid = styled(VariableSizeGrid) <MainGridProps>`
overflow-y: scroll;
box-sizing: content-box;
${props => {
if (!props.hideVerticalScrollbar)
return '';
const paddingDir = (props.theme.dir === 'rtl' ? 'padding-left' : 'padding-right');
return `${paddingDir}: ${SizeUtils.scrollbarWidth}px;`;
}}
`;
export const GridShadow = styled(MainGrid)`
opacity: 0;
`;
κ·Έλ° λ€μ λ€λ₯Έ νμΌμμ:
<SyncableGrid
mainGridRef={this.firstGridMain}
shadowGridRef={this.firstGridShadow}
onScroll={this.handleFirstGridScroll}
// other props omitted for bravity...
>
// children omitted for bravity...
</SyncableGrid>
<SyncableGrid
mainGridRef={this.secondGridMain}
shadowGridRef={this.secondGridShadow}
onScroll={this.handleSecondGridScroll}
// other props omitted for bravity...
>
// children omitted for bravity...
</SyncableGrid>
private handleFirstGridScroll = (e: GridOnScrollProps) => {
const { scrollTop, scrollLeft } = e;
// synchronize self
if (this.firstGridMain.current) {
this.firstGridMain.current.scrollTo({ scrollTop, scrollLeft });
}
// synchronize other grid
if (this.secondGridMain.current) {
this.secondGridMain.current.scrollTo({ scrollTop, scrollLeft });
this.secondGridShadow.current.scrollTo({ scrollTop, scrollLeft });
}
}
@alonrbar 맀λ ₯μ
κ·Έλ¦Όμ 격μκ° μ€μ 격μ μμ μλ κ²μ²λΌ 보μ΄μ£ ? κ·Έλ λ€λ©΄ "μ€μ 그리λ"μ ν΄λ¦ μ΄λ²€νΈκ° μλνμ§ μμ΅λκΉ? ν΄λ¦ μ΄λ²€νΈ + x/y μ’νλ‘ μ½κ°μ ν΄νΉμ ν μ μκ³ μ΄λ»κ²λ λ©μΈ 그리λμ μ μ©ν μ μλ€κ³ κ°μ ν©λλ€.
λν @barbalex re: Windowsμμλ μ€ν¨ν©λλ€.
μ€μ λ‘λ ν¬λ‘¬ νλκ·ΈμΌ μ μμ΅λλ€. chrome://flags μ λ΄μ©μ΄ μλμ§ νμΈ
μ΄ λ¬Έμ λ νμ€ν λΈλΌμ°μ μ λλ©μ΄μ νλ μλ³΄λ€ λΉ λ₯΄κ² "λΆλλ½κ²" μ€ν¬λ‘€νλ κ²κ³Ό κ΄λ ¨μ΄ μλ κ² κ°μ΅λλ€. μμ ν μ±λ₯/μ§μ° λ¬Έμ κ° μ°λ €λλ κ²½μ° λ§€μ° κΈ°λ³Έμ μΈ μ€ν¬λ‘€ λκΈ°ν ꡬν(ν divμ μ€ν¬λ‘€ μ λ€λ₯Έ divμ μ€ν¬λ‘€ μμΉ μ€μ )μ μλνκ³ λμΌν λ¬Έμ κ° λ°μνλμ§ νμΈνμμμ€. Reactλ₯Ό λ²μΈμΌλ‘ μ κ±°νκΈ° μν΄ μμν λ°λλΌ JSμμ ν μλ μμ΅λλ€.
Ahhh @ranneyd λΉμ λ§μ΄ λ§μμ ν΄λ¦ μ΄λ²€νΈλ₯Ό μ°¨λ¨ν©λλ€... κ·Έκ²μ λν΄ λ μκ°ν΄μΌ ν©λλ€...
chrome://flags μ μ€λ λ μ€ν¬λ‘€ κΈ°λ₯μ΄ ν° μν₯μ λ―ΈμΉλ€κ³ μκ°ν©λλ€. μ΄ κΈ°λ₯μ λλ©΄ λ§μ°μ€ ν λ‘ μ€ν¬λ‘€νλ κ²μ΄ μ€ν¬λ‘€ λ§λλ‘ μ€ν¬λ‘€νλ κ²λ§νΌ λΆλλ½κ² λ©λλ€.
@alonrbar μ΄κ²μ
λ©μΈ 그리λμ μ€ν¬λ‘€ νΈλ€λ¬λ₯Ό μΆκ°ν©λλ€. κ±°κΈ°μμ e.preventDefault();
λλ μ€μ μ€ν¬λ‘€μ λ°©μ§νκΈ° μν΄ λ¬΄μΈκ°λ₯Ό μνν©λλ€. κ·Έλ° λ€μ μ΄λ²€νΈλ₯Ό λ³΄κ³ μΌλ§λ λ§μ΄ μ€ν¬λ‘€λμλμ§ νμ
ν©λλ€. μ΄λ λ€λ₯Έ λκΈ°νλ νλͺ©μ μ΄λνλ λ° μ¬μ©λμ§λ§ λμΌν μμλ₯Ό μλμΌλ‘ μ€ν¬λ‘€νλ λ° μ¬μ©ν©λλ€. λ°λΌμ Aλ₯Ό μ€ν¬λ‘€νλ λμ ν΄λΉ μ 보λ₯Ό μ¬μ©νμ¬ Bλ₯Ό μ€ν¬λ‘€νλ λμ Aμμ μ€ν¬λ‘€μ κ°λ‘μ±κ³ μ·¨μν λ€μ Bμ A μ체λ₯Ό μ€ν¬λ‘€νλ λ° μ¬μ©ν©λλ€. κ·Έκ² ν¨κ³Όκ° μμκΉμ?
λλ ν μ€νΈνκΈ° μν΄ μ»΄ν¨ν° μμ μμ§ μμ΅λλ€. κ½€ hackyνμ§λ§ λλ μΌν μ μμ΅λλ€. @bvaughn μκ°?
@barbalex λ§μ΅λλ€. μ μκ²λ ν¨κ³Όμ μ΄μ§λ§ λͺ¨λ μ¬μ©μκ° ν¬λ‘¬ νλκ·Έλ₯Ό μΌκ³ λ μλ μμ΅λλ€ π
@ranneyd λ°©κΈ μ΄ν΄λ³΄κ³ μμ€ μ½λ( link )λ‘ μ½κ° λ§μ§μκ±° λ Έμ§λ§ λΆλͺ ν μ€ν¬λ‘€ μ΄λ²€νΈλ₯Ό λΉνμ±νν μλ μμ΅λλ€. μ€ν¬λ‘€ μ΄λ²€νΈλ₯Ό μ λ°ν μ μλ λͺ¨λ λ§μ°μ€ ν , ν°μΉ λ° ν€λ³΄λ μ΄λ²€νΈλ₯Ό κ°λ‘μ±λ κ²λΏ κ·Έλ€μ λ°©μ§νμμμ€. λ§ν¬(SO)μλ μ΄μ λν 짧μ μ½λ μ€λν«μ΄ μμ§λ§ μ΄λ‘ μΈν΄ ν¨μ¬ ββλ ν΄νΉλκΈ° λλ¬Έμ μ¬μ ν κ·Έκ²μ λν΄ μκ³ νκ³ μμ΅λλ€...
@alonrbar μ, μ¬μ©μμκ² μ΄ μμ μ μννλλ‘ μμ²νλ©΄ μλνμ§ μμ΅λλ€. μλνλ €λ _do_ κ²½μ° _ν μ__ μλ λ§ν¬: chrome://flags/#disable -threaded-scrolling
@alonrbar μ΄ μ΄κ²μ μ’μ§ μμ§λ§ μ΄λ―Έ ν¨κ» ν΄νΉν 그리λμ μ μ©νλ κ²½μ°
κ·Έλ₯ μ€ν¬λ‘€ ν μ΄μ£ ? νμ΄ν ν€λ λ°μν©λκΉ?
μ΄κ²μ νμ©λλ λ΅λ³μ μ€λν«μ λλ€. https://stackoverflow.com/questions/4770025/how-to-disable-scrolling-temporarily
function disableScroll() {
if (window.addEventListener) // older FF
window.addEventListener('DOMMouseScroll', preventDefault, false);
document.addEventListener('wheel', preventDefault, {passive: false}); // Disable scrolling in Chrome
window.onwheel = preventDefault; // modern standard
window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE
window.ontouchmove = preventDefault; // mobile
document.onkeydown = preventDefaultForScrollKeys;
}
보μλ€μνΌ μ²λ¦¬ν΄μΌ νλ λͺ κ°μ§ μ΄λ²€νΈκ° μκ³ κ·Έλ κ² ν¨μΌλ‘μ¨ λ°μν μ μλ κ²°κ³Όλ₯Ό κ³ λ €ν΄μΌ ν©λλ€.
νμ¬λ‘μλ μ΄ λ¬Έμ λ₯Ό ν΄κ²°νλ λ° λ λ§μ μκ°μ ν¬μν μ μκΈ° λλ¬Έμ κ°μμ΄ μλ μ루μ
μ μ¬μ©νκΈ°λ‘ κ²°μ νμ΅λλ€(μλ²½νμ§λ μμ§λ§ μ μ¬μ© μ¬λ‘μ λ μ ν©ν¨). μ¬κΈ° μ μ¬κΈ°μμ λ΄κ° μ¬μ©νλ μ½λλ₯Ό μ°Ύμ μ μμ΅λλ€( react-window
λνν λΌμ΄λΈλ¬λ¦¬μ μΌλΆμ
λλ€).
@alonrbar μ SO μ루μ μ΄ λ§€μ° ννΈμλ€λ λ° λμν©λλ€.
κ·Έλ¬λ κ·νμ μ루μ μ λ§€μ° ν₯λ―Έλ‘μ΅λλ€. λλ κ·Έκ²μ μ€μ€λ‘ ν΄κ²°νκ³ κ°μνλ ν μ΄λΈκ³Ό ν¨κ» μλνλλ‘ λ§λ€ μ μλμ§ νμΈνλ €κ³ ν©λλ€.
@alonrbar κ·Έλμ μ€μ λ‘ μ λ μμΉ μ§μ μ μ¬μ©νλ λΉκ°μν ꡬνμ λ§λ€μμ΅λλ€. μ€ν¬λ‘€λλ μ μΌν κ²μ μΈλΆ 컨ν
μ΄λμ
λλ€. μ€ν¬λ‘€ μ λ΄λΆ μμμ μ λ μμΉλ₯Ό μ§μ νλ λ° μ¬μ©λλ μλ¨/μΌμͺ½ κ°μ μ
λ°μ΄νΈν©λλ€. κ·Έλμ λ΄κ° λ°κ²¬ν scrollTo
λλ scrollTop = ...
λ μ μκ² λ§μ μ¬νμ μ겨주μμ΅λλ€. κ·Έ μμ μ€ν¬λ‘€ λ§λλ νμ μ 체 그리λ μΈλΆμ μμ΅λλ€.
λ΄κ° λ§λ μ΄ κ²μ λͺ¨λ λ©΄μ "κ³ μ ν€λ"λ₯Ό λμ μΌλ‘ κ°μ§ μ μμ΅λλ€. κ·Έκ²μ λ§€μ° κ±°μΉ μ/pocμ λλ€.
λΆλͺ ν μ¬κ°ν λ¬Έμ μΈ κ°μνκ° λΆμ‘±ν©λλ€. λΆννλ μ΄ λΌμ΄λΈλ¬λ¦¬λ κΈ°λ³Έμ μΌλ‘ μ€ν¬λ‘€λ§μμ μ€νλκ³ μ΄κ²μ λ΄λΆ 그리λ μ€ν¬λ‘€μ μ κ±°νκΈ° λλ¬Έμ μ΄ λΌμ΄λΈλ¬λ¦¬μμ 그리λλ₯Ό λνν μ μλμ§ λͺ¨λ₯΄κ² μ΅λλ€. λ€μ λ¨κ³κ° 무μμΈμ§ νμ€νμ§ μμ΅λλ€.
https://codesandbox.io/embed/non-virtual-scroll-synced-table-ot467
μ΄ λΌμ΄λΈλ¬λ¦¬μ μ°λ£λ₯Ό 곡κΈνλ λμΌν κ°μν λ Όλ¦¬κ° μ¬κΈ°μ μ μ©λ μ μλ€κ³ μκ°ν©λλ€.
@ranneyd μμ£Ό λ©μ§ ꡬνμ λλ€!
μλμ μΈ κ·Έλ¦¬λ ꡬμ±μ΄ μ’μμ :)
κ·Έλ¬λ κ°μ₯ μ€μν κ²μ μ€ν¬λ‘€λ§ λμ μ λ μμΉ μ§μ μ μ¬μ©νλ μμ΄λμ΄κ° μ΄ λ¬Έμ λ₯Ό ν΄κ²°νλ μ΄μ μΌ μ μλ€λ κ²μ λλ€. λ€λ₯Έ div λ₯Ό λμ
react-window
μ render
λ©μλμ μ°κ²°ν μ μλ€λ©΄ 459ν μ΄μμ ꡬνμΌλ‘ λ체ν μ μμ΅λλ€. κ·Έλ° λ€μ onscroll μ΄λ²€νΈλ₯Ό μ°κ²°νκ³ νμν λ κ·Έ ν¨κ³Όλ₯Ό λΉνμ±νν μ μμ΅λλ€(μ€ν¬λ‘€ λ§λλ κ³μ μ΄λνμ§λ§ λ΄μ©μ΄ λ³κ²½λμ§ μλλ‘ μ μ΄ν μ μμ).
@alonrbar κ·Έλμ μ€μ λ‘ κ°μν μκ³ λ¦¬μ¦μ λ€μ ꡬννμ΅λλ€. μ’μ§λ μμ§λ§ μ΄ Gridκ° μ€μ κ°μνμ λλ¬νμ λ μμ€ μ½λλ₯Ό 보면 κΈ°λ³Έμ μΌλ‘ λμΌν algμ λλ€. κ·Έλ¬λ μ€μ λ‘ μ±λ₯μ μ€μν©λλ€. μ§μ° μμ΄ 200x200 그리λμ λλ¬νκ³ μ½κ°λ§ μμΌλ©΄ 500x500μ λλ¬ν μ μμ΅λλ€. λ΄ μμ¬κ° λ μ΄μ μ΄ μμ μ μννλλ‘ νλ©΄ μ μν λλ‘ λ λλ§ λ©μλ ꡬνμ μλν κ²μ λλ€. μ΄λ μλ§λ μ€μ λ‘ λ§€μ° μ¬μΈ κ²μ λλ€.
λ΄κ° λ§λ 그리λμ κ΄μ¬μ΄ μμΌμλ©΄ μ΄λκ°μ κ²μ ν μ μμ΅λλ€. λΉμ μ΄ κ·Έκ²μ κ°μ Έ μμμ΄ λΌμ΄λΈλ¬λ¦¬μ μ°κ²°νλ €λ©΄ λ΄ μλμ΄ λμμμ€ π
@ranneyd λ€, λΉμ μ΄ λ§λ κ°μν μ루μ μ λ³΄κ³ μΆμ΅λλ€. λ΄κ° κ·Έκ²μ μ¬μ©ν μ§λ λͺ¨λ₯΄κ² μ§λ§ νμ€ν ν₯λ―Έλ‘μΈ κ²μ λλ€ :)
λν μ€λ μ μν λλ‘ λ λλ§ λ°©λ²μ λν λ³κ²½ μ¬νμ ꡬννκΈ° μν΄ κ·νμ μ½λλ₯Ό μ¬μ©νλ €κ³ μλνμ§λ§ μ½λλ₯Ό λ€μ μ½μ ν μκ°νλ λ°©μμΌλ‘ μ€ν¬λ‘€λ§μ μ€μ λ‘ μ°κ²° ν΄μ νμ§ μμ κ²μΌλ‘ λνλ¬μ΅λλ€. λ΄ λ§μ μ€ν¬λ‘€ λ§λμ onscroll
μ΄λ²€νΈκ° μ¬μ ν μ€μ μ½ν
μΈ μ€ν¬λ‘€κ³Ό λΆλ¦¬λ μ μλ€λ κ²μ
λλ€. λλ λΉμ μ μμ΄λμ΄λ₯Ό ν λ¨κ³ λ λ°μ μμΌ μ§μ μΌλ‘ μ°κ²°μ΄ λκΈ΄ μ€ν¬λ‘€μ ꡬννμ΅λλ€.
https://codesandbox.io/embed/absolute-position-scrolling-1u7vj
μ½λλ₯Ό 보면 Content
κ΅¬μ± μμ μμ top
λ° left
μμ±μ μ κ±° νλ©΄ μ€ν¬λ‘€ λ§λκ° ν . μ΄λ²μλ λ§μ°μ€ μ΄λ²€νΈκ° μ°¨λ¨λμ§ μλ κ²λ νμΈνμ΅λλ€. π
μ΄μ μ΄ κ΅¬νμ μ¬μ©νμ¬ onscroll
μ΄λ²€νΈλ₯Ό 무μνκ³ μ¬λ¬ 그리λλ₯Ό μλμΌλ‘ λκΈ°νν μ μλ€κ³ μκ°ν©λλ€. νμ§λ§ λ¬Όλ‘ λ λ§μ μμ
μ΄ νμνλ―λ‘ λ€μ μκ°μ κΈ°λ€λ €μΌ ν©λλ€...
μ΄ ν λ‘ μ μ μκ² νΈκΈ°μ¬μ λΆλ¬μΌμΌμΌ°μ΅λλ€. κ·Έλμ λ κ°μ μ€ν¬λ‘€ λκΈ°νλ react-window Grid
react-virtualized MultiGrid
μ λΉκ΅νλ νλ‘μ νΈλ₯Ό μ€μ νμ¬ μ±λ₯μ΄ μ΄λ»κ² λΉκ΅λλμ§ μ μ μμ΅λλ€. :
https://github.com/bvaughn/react-window-vs-react-virtualized-synced-grids
κ°κ°μ μ¬μ©λ²μ μ΅λν λΉμ·νκ² λ§λ€λ €κ³ λ Έλ ₯νμ΅λλ€. μΌλΆ μ΄κΈ° κ΄μ°°:
onScroll
(μ»€λ° μ€μ νΈμΆλλ) λμ "λ€μ΄ν°λΈ"(React) μ€ν¬λ‘€ μ΄λ²€νΈ νΈλ€λ¬(Reactμ μΌκ΄ μ
λ°μ΄νΈ λ΄μμ νΈμΆλ¨) μ λ¬μ μ§μνκΈ° μν΄ Grid
μ ν¨μΉλ₯Ό λ§λ€μμ΅λλ€. λ¨κ³). μ΄κ²μ λ³λμ κ³λ¨μ λ λλ§μ λ°©μ§νκΈ° λλ¬Έμ λ‘컬μμ ν
μ€νΈνμ λ λ§€μ° μ λ§ν λ³κ²½ μ¬νμΈ κ² κ°μ΅λλ€. λ°λΌμ κΈ°λ³Έ onScroll
νμ΄λ°μ λ³κ²½νκ² μ΅λλ€.@bvaughn divA -> onScroll -> setState -> ref.scrollTopμ μ¬μ©νμ¬ κ°μ₯ κΈ°λ³Έμ μΈ λ°λλΌ μ€ν¬λ‘€ ν¨κ³Ό μ½λλ₯Ό λ§λ€λ €κ³ μλνμ§λ§ μ¬μ ν μ΄ ν¬λ‘¬ μ€λ λ μ€ν¬λ‘€λ§ λ¬Έμ λ₯Ό ν΄κ²°ν μ μμμ΅λλ€. λλ λΆλͺ ν λ°μ μνλ₯Ό μ°ννμ§ μμκ³ onScroll νΈλ€λ¬ λ΄μμ ref.scrollTopμ μ€μ νμ§λ§ κ·Έ μΈμλ λ κΈ°λ³Έμ μΈ λ°©λ²μ μκ°ν μ μμ΅λλ€. κ°λ₯ν ν μ μ μμ λ¨κ³μμ μΆ©λΆν λΉ λ₯΄κ² onScroll -> scrollTopμ μ»μ μ μλ€λ©΄ μ΄λ»κ² μμ ν©λκΉ? λ΄κ° λκ°λ₯Ό μμ ν λμΉκ³ μμ΅λκΉ? μ€ν¬λ‘€(λλ scrollTop μ€μ )μ κΈ°λ°μΌλ‘ 그리λλ₯Ό μ΄λν νμκ° μλ κ² κ°μ΅λλ€.
λͺ©νλ νμ JavaScriptκ° μ€ν¬λ‘€μ κ΄λ¦¬νλ μ€λ λλ₯Ό λ°λΌκ° μ μλλ‘ μ΅λν λΉ λ₯΄κ² νλ κ²μ λλ€.
λλ λ°μ μνλ₯Ό μ°ννμ§ μμκ³ onScroll νΈλ€λ¬ λ΄μμ ref.scrollTopμ μ€μ νμ΅λλ€.
λͺ νννκΈ° μν΄ μ΄κ²μ λ΄ repoλνλ μΌμ΄ μλλλ€. λλ μ‘ν°λΈ 그리λμ λμΌν (React-wrapped) μ΄λ²€νΈ νΈλ€λ¬μ ν¨μλΈ κ·Έλ¦¬λμμ μ€ν¬λ‘€ μ€νμ μ μ€μ νκ³ μμΌλ―λ‘ Reactλ μ λ°μ΄νΈλ₯Ό λ¨μΌ λ λ+컀λ°μΌλ‘ μΌκ΄ μ²λ¦¬ν©λλ€. μ΄κ²μ μλ§λ μμ§ν _λ§μ_ μ°¨μ΄λ₯Ό λ§λ€μ§ μμ κ²μ λλ€.
@ranneyd μ @bvaughn μ΄ μ§κΈκΉμ§ κ΄μ°°ν
λ§μ ꡬνμ΄ λ°μ€ν¬ν λΈλΌμ°μ μμ μΆ©λΆν μ μλνμ§λ§, μ μ£Όμ μ¬μ© μ¬λ‘λ μ€μ λ‘ λͺ¨λ°μΌ μ₯μΉμ μμΌλ©° κ±°κΈ°μμ μμ²λ μ±λ₯ μ°¨μ΄λ₯Ό λ΄ λλ€.
λ κ°μ λ¨μν λΉκ°μ 그리λλ₯Ό λκΈ°ννλ κ²μ κ½€ μ μλν©λλ€(100% μλ²½νμ§λ μμ§λ§ λͺ¨λ°μΌμμλ μΆ©λΆν κ°κΉμ΅λλ€). μ΄κ²μ λ΄ μμ§νμ§λ§ μλνλ ꡬν μ΄λ©° μ€μ λ‘ μλνλ κ²μ 보기 μν ν
μ€νΈ μΌμ΄μ€μ
λλ€ ( yarn storybook
).
"μ μ΄λ" μ€ν¬λ‘€μ μ¬μ©νλ©΄( μ΄ μ£Όμμμ μ μν λλ‘) λ 그리λλ₯Ό 100% λκΈ°ν μνλ‘ μ μ§νμ§λ§ λ°μ€ν¬ν±μμλ μλΉν λλ¦¬κ³ λͺ¨λ°μΌμμλ μμ ν λ무 λ립λλ€. μ΄κ²μ (λ§€μ° κ±°μΉ ...) λ΄ κ· μ΄μ λλ€. https://github.com/alonrbar/react-window/commit/c39ce7006dbd590d9c640e37f8a1e78826e4688e
κ·ΈλΌμλ λΆκ΅¬νκ³ "ν΅μ λ" μ λ΅ μ΄ λ¨μΌ κ°μ λͺ©λ‘μμ
λ λΆμ΄ μ΄λ―Έ μ μν κ²μ²λΌ _callPropsCallbacks
λ₯Ό _onScroll
μ²λ¦¬κΈ°λ‘ μ§μ μ΄λνλ©΄ λκΈ°ν μ§μ°μ μ΅μννλ λ° λμμ΄ λ μ μλ€κ³ μκ°νμ΅λλ€. νΈμ§ - μ§κΈ μλνμ§λ§ μ€μ λ‘ λμμ΄λμ§ μμμ΅λλ€ π
μ΄λ€ μμΌλ‘λ IMHOλ κ΅¬μ± μμμ λλ¨Έμ§ λΆλΆ(νν¬μΌ μλ μμ)μμ κ°μν λ Όλ¦¬λ₯Ό λΆλ¦¬νμ¬ λ λλ§ λ° μ¨μ€ν¬λ‘€ νλͺ©μ λ³λλ‘ μ²λ¦¬νκ³ μ½κ² λΉκ΅νκ³ λ°νμμ μ νν μ μλλ‘ νλ κ²μ΄ μ’μ΅λλ€. κ΅¬μ± μν. λν μ΄ λ Όλ¦¬λ₯Ό λ΄λ³΄λ΄κ³ μ¬μ©μκ° λμΌν λ Όλ¦¬λ₯Ό κΈ°λ°μΌλ‘ μ¬μ©μ μ§μ κ΅¬μ± μμ(μ: μ΄ μ£Όμμ @ranneyd μ루μ )λ₯Ό ꡬνν μ μμ΅λλ€.
μκ°?
@alonrbar μ λ μμΉ μ§μ μ μννλ λ΄ μ루μ
μ μ€ν¬λ‘€μ μννλ 그리λκ° μμΌλ―λ‘ μ½ 300x300κΉμ§ λ§€μ° μ μλν©λλ€. μ½κ° μ§μ°λ©λλ€). λ ν° ν¬κΈ°μμλ ν° λ°°μ΄μ λν μ²λ¦¬/맀νμ΄λΌκ³ μκ°ν©λλ€. λͺ κ°μ§ μ΅μ νκ° μλ€κ³ μκ°ν©λλ€.
νμ§λ§ ν μλ μμ΅λλ€. μ μλΉν κ°λ¨ν κ°μν ꡬνλ§νΌ μ€ν¬λ‘€ λκΈ°νμ κ΄λ ¨μ΄ μλ€κ³ μμ ν νμ ν μλ μμ΅λλ€. μλ₯Ό λ€μ΄ λ λ§μ μΊμ±μ μνν μ μκ³ λ λλ§ κΈ°λ₯μ μ ν νΈμΆνμ§ μκΈ° μν΄ μ
μ λ μΌμ° κ°μνν΄μΌ νλμ§ μ¬λΆλ₯Ό κ³μ°ν μ μμ΅λλ€.
λλ λͺ¨λ°μΌμμ μ무κ²λ ν μ€νΈνμ§ μμμ΅λλ€. μ μ νμ μλν΄ λ³Ό μ μλ λͺ κ°μ§ μ½λλ₯Ό μ 곡νκ² μ΅λλ€.
@bvaughn ν μ€νΈλ₯Ό μ λ§ λ³΄κ³ μΆμ΅λλ€. κ·Έλ λ€μ΄ν°λΈ μ€ν¬λ‘€μ μ§μ μ°κ²°νλ©΄ λ¬Έμ κ° ν΄κ²°λμ§λ§ λΉμ μ κ·Έλ μ§ μλ€κ³ λ§ν©λλ€. μ§μ λ³΄κ³ μΆμ΅λλ€.
κ°μν λ Όλ¦¬λ₯Ό νν¬ λλ λ 립 κΈ°λ₯μΌλ‘ λμ΄μ€λ ν, λ Όλ¦¬κ° λ³Έμ§μ μΌλ‘ λ·°μ μ°κ²°λμ΄ μκΈ° λλ¬Έμ μλΉν κΉλ€λ‘μμ§λλ€. λν λ§μ μ±λ₯ μ‘°μ μλ νλμ νν¬ λλ κΈ°λ₯μΌλ‘ μΊ‘μννκΈ° μ΄λ €μΈ μ μλ μΊμ± λ° λ©λͺ¨μ΄μ μ΄μ νλͺ©μ΄ ν¬ν¨λκ±°λ μ΅μν λμΌν μ±λ₯μ μ»μ μ μλ μ λμΈ κ² κ°μ΅λλ€. κ·Έλ¬λ λλ λ΄κ° κ°μ§ κ²μ λ³΄κ³ μΌλ§λ λ§μ λ Όλ¦¬λ₯Ό λμ΄λΌ μ μλμ§ λ³Ό κ²μ λλ€.
μΆμ :
μλ§ μλνμ§ μμ κ²μ΄λΌκ³ λ°©κΈ μκ°ν ν κ°μ§λ denounceμ κ°μ κ² + CSS μ νμ μννλ κ²μ
λλ€. 100msλ§λ€ νλμ μ€ν¬λ‘€ μ΄λ²€νΈλ§ μ€ννκ³ μμ§μμ μ λλ©μ΄μ
νλ©΄ λ μ’μ λ³΄μΌ μ μμ΅λλ€. λν μλΉν λ λ°μμ μΌλ‘ λ³΄μΌ μλ μμ΅λλ€. μλ μ€λΈ μν¬λννΈμ λΉμ·ν©λλ€(μ§μ° λλ κΈ΄ λκΈ° μκ°μ΄ μλ κ²½μ° μΊλ¦ν°λ₯Ό μ§μ μΌλ‘ μ΄λν λ€μ μ€μ λ‘ μ΄λν μμΉμ λν μ 보λ₯Ό μ»μ ν μμ ν©λλ€).
@bvaughn ν μ€νΈλ₯Ό μ λ§ λ³΄κ³ μΆμ΅λλ€. κ·Έλ λ€μ΄ν°λΈ μ€ν¬λ‘€μ μ§μ μ°κ²°νλ©΄ λ¬Έμ κ° ν΄κ²°λμ§λ§ λΉμ μ κ·Έλ μ§ μλ€κ³ λ§ν©λλ€. μ§μ λ³΄κ³ μΆμ΅λλ€.
μ λ κ·Έλ κ² λ§νμ§ μμμ΅λλ€ :smile: λ¨μ§ λΆνμν λ λλ§κ³Ό DOM λ³νμ λ°©μ§νλ€κ³ λ§νμ΅λλ€. μ€μ μ±λ₯μ λ―ΈμΉλ μν₯μ΄ μ΄λ μ λμΈμ§ λμκ²λ λΆλΆλͺ ν©λλ€. κ·ΈλΌμλ λΆκ΅¬νκ³ μ λ°μ μΌλ‘ κΈμ μ μΈ λ³νμΈ κ² κ°μ΅λλ€.
@alonrbar @bvaughn μ€μ λ‘ λ΄ μ½λλ₯Ό λ¬Έμνν΄μΌ νμ§λ§ μ¬κΈ°μ μ΅μ λ²μ μ΄ μμ΅λλ€.
@alonrbar @bvaughn κ·Έλμ μ¬κΈ° λ΄κ° λ°©κΈ λ°κ²¬ν μ¬λ―Έμλ κ²μ΄ μμ΅λλ€:
λ΄ μ루μ
μ macbook νλ©΄μ Chrome 75μμ μλνμ§ μμ΅λλ€. λλ£κ° ν¬λ‘¬μ μ
λ°μ΄νΈνμ§ μμμ λ μλνμ΅λλ€. μΈλΆ λͺ¨λν°λ₯Ό μ¬μ©νλ©΄ μλν©λλ€. λ
ΈνΈλΆ νλ©΄μμλ μ§μ°λ©λλ€.
π©
ν ... μΈλΆ λͺ¨λν°μ μ¬μλ₯ μ΄λ λ°°μ¨μ μ½κ°μ μ°¨μ΄κ° μμ΅λλ€. "μλνμ§ μμ΅λλ€"λΌκ³ λ§νλ©΄ ꡬ체μ μΌλ‘ 무μμ μλ―Έν©λκΉ?
λ΄ μλͺ»μ΄μΌ. μ€ν¬λ‘€μ΄ λ μ΄μ λκΈ°νλμ§ μμμ μλ―Έν©λλ€. λ΄ repoλ₯Ό 볡μ νμ¬ μ€ννλ©΄ μΈλΆ λͺ¨λν°μ λ ΈνΈλΆ νλ©΄μ λΉκ΅ν μ μμ΅λλ€. λͺ¨λν°μμ κ·Έλ€μ μλ²½νκ² λκΈ°νλ©λλ€. λ©ν± νλ©΄μμ ν€λκ° κΉλ°μ λλ€(μ€ν¬λ‘€λ§ μμμ λμΌν μλλ‘ μ λ°μ΄νΈνμ§ μμ).
λλ μ€μ λ‘ ν¬κΈ°νκ³ position: sticky
μλνκ³ μμ΅λλ€. κ·Έκ²μ μ€μ λ‘ μλν©λλ€. λΈλΌμ°μ μ§μμ΄ 100%λ μλμ§λ§ μ€μ λ‘λ 1λ
μ λ³΄λ€ ν¨μ¬ λμμ‘μ΅λλ€.
μλν μ μλ ν΄λ¦¬νμ΄ μλ ν΄λ¦¬νμΈ μ΄ λΌμ΄λΈλ¬λ¦¬κ° μμ§λ§ μ°λ¦¬κ° λͺ©νλ‘ νλ λΈλΌμ°μ λ μ°μ°ν μ΄ κΈ°λ₯μ μ§μν©λλ€.
https://github.com/dollarshaveclub/stickybits
@alonrbar @bvaughn μ΄ μ΅μ λ²μ μ
λλ€. position: sticky
ν©λλ€. readmeμμ μ‘°κΈ μ€λͺ
νκ² μ΅λλ€. μ½λλ μ¬μ ν λ¬Έμνν΄μΌ ν©λλ€.
λ΄ μ루μ μ macbook νλ©΄μ Chrome 75μμ μλνμ§ μμ΅λλ€. λλ£κ° ν¬λ‘¬μ μ λ°μ΄νΈνμ§ μμμ λ μλνμ΅λλ€. μΈλΆ λͺ¨λν°λ₯Ό μ¬μ©νλ©΄ μλν©λλ€. λ ΈνΈλΆ νλ©΄μμλ μ§μ°λ©λλ€.
π©
@ranneyd μ€λ
@bvaughn κ·ΈλμΌ νλ€κ³ μκ°ν©λλ€. OSλ 60hzλ₯Ό 보λ΄κ³ μλ€κ³ λ§νκ³ λͺ¨λν° μ¬μμ 60hzλΌκ³ μκ°νμ§λ§ λκ΅°κ°κ° κ±°μ§λ§μ ν΄λ λλΌμ§ μμ κ²μ λλ€ π
@ranneyd μ§κΈμ useVirtual
νν¬ λ° λ λλ§μμ λ‘μ§μ μ°μνκ² λΆλ¦¬ν©λλ€.
react-window
λν pull μμ²μ μ΄λ»κ²λ μμ±νκ³ κ±°κΈ°μμ μ¬μ©νκ³ λ λ λ‘μ§μ μ°κ²°ν μ μλ μΌμ’
μ renderTable
λ©μλλ₯Ό λ
ΈμΆν μ μλ€λ©΄ μ’μ κ² κ°μ΅λλ€. μ΄λ κ²νλ©΄ λΌμ΄λΈλ¬λ¦¬κ° λ°μ μ°½μ κ΅μ²΄νλ λμ λνν μ μμ΅λλ€. λλ μ°λ¦¬κ° μ΄ μ κ·Ό λ°©μμ νμ©νκ³ μ΄λ―Έ λ§μ ν
μ€νΈλ₯Ό κ±°μ³€κ³ λ리 νΌμ§ react-window
λ΄λΆμ λ¬Έμ λ₯Ό ν΄κ²°ν μ μλ€λ©΄ μ νΈν κ²μ΄λΌκ³ λ―Ώμ΅λλ€.
λ€λ₯Έ λ¬Έμ λ‘, scrollTo
κ° μ§μ DOM μ‘°μμ μ¬μ©νλ€λ©΄(μνλ₯Ό μ€μ νλ κ² μΈμ μ΄λ€ κ²½μ°λ κ·Έλ κ² νκΈ° μ μ) λ ν
μ΄λΈμ λκΈ°ννλ κ²°κ³Όκ° λ λΆλλ¬μμ§ κ²μ΄λΌκ³ μκ°ν©λλ€. λ΄κ° μ°©κ°νμ§ μλλ€λ©΄ @bvaughn μ λνμ΄ λ°©ν₯μΌλ‘ 무μΈκ°λ₯Ό μ μνκ³ μμμ΅λλ€.
@ranneyd κ·νμ κ³ μ ν
μ΄λΈ μ루μ
μ μ λ§ νλ₯ν΄ λ³΄μ΄λ©° μ¬μ©ν μ μκ² λμ΄ λ§€μ° κΈ°μ©λλ€. npm
μ μ¬μ©ν μ μλ APIλ₯Ό μΆμνλ κ²μ κ³ λ €νμκ² μ΅λκΉ?
@bvaughn @ranneyd
κ·Έλμ κ½€ μ€λ μκ°μ΄ μ§λ ν λλ μ΅κ·Όμ μ΄ λ¬Έμ λ‘ λμμμ΅λλ€. λΌμ΄λΈλ¬λ¦¬μ Recyclerlistview λ° react-virtual-gridμ μ½λμ μμ΄λμ΄λ₯Ό μ¬μ©νμ¬ λ§μΉ¨λ΄ μνλ λμ, μ¦ λ°μ€ν¬ν±κ³Ό λͺ¨λ°μΌ λͺ¨λμμ μ μλνλ κ³ μ λ νκ³Ό μ΄μ΄ μλ κ³ μ±λ₯ 그리λλ₯Ό λ¬μ±ν μ μμμ΅λλ€. μ₯μΉ(λΉ/λ°±μ μ μμ΄ λΆλλ¬μ΄ μ€ν¬λ‘€).
κ·Έκ²μ TLDRμ λ΄κ° λμ ν μμΉ μ§μ κ³Ό ν¨κ» μ¬νμ©μ μ¬μ©νλ€λ κ²μ΄κ³ κ°μ₯ ν₯λ―Έλ‘μ΄ μ½λλ μ΄ λ°©λ² μμ μ°Ύμ μ μλ€λ
λ λ€λ₯Έ μ루μ μ μμ±νκ² λ λκΈ°μ λν ν¬λ λ§ λ±μ΄ μ¬κΈ°μ μμ΅λλ€ . κ°μ¬ ν΄μ!
λμ€μ λ€λ₯Έ μ¬λμ΄ μ΄ λ¬Έμ λ₯Ό λ°κ²¬ν κ²½μ°λ₯Ό λλΉνμ¬ μμ μ€μΈ Code Sandbox μμ μ λν λ§ν¬λ₯Ό μ¬κΈ°μ λ¨κΈΈ κ²μ λλ€.
https://codesandbox.io/s/y3pyp85zm1
μμ£Ό μ’μ΅λλ€. μμ ν μ€λ₯Έμͺ½μΌλ‘ μ€ν¬λ‘€ν λκΉμ§: κ·Έλ¬λ©΄ ν€λκ° λ΄μ©κ³Ό μλͺ» μ λ ¬λ©λλ€(μ€ν¬λ‘€ μμ§ μ€ν¬λ‘€ λ§λμ λλΉλ§νΌ).
νΉμλΌλ κ·Έ ν΄κ²°μ±
μ μ°Ύμκ² μ΅λκΉ?
κ°μ¬ ν΄μ
λμ€μ λ€λ₯Έ μ¬λμ΄ μ΄ λ¬Έμ λ₯Ό λ°κ²¬ν κ²½μ°λ₯Ό λλΉνμ¬ μμ μ€μΈ Code Sandbox μμ μ λν λ§ν¬λ₯Ό μ¬κΈ°μ λ¨κΈΈ κ²μ λλ€.
https://codesandbox.io/s/y3pyp85zm1μμ£Ό μ’μ΅λλ€. μμ ν μ€λ₯Έμͺ½μΌλ‘ μ€ν¬λ‘€ν λκΉμ§: κ·Έλ¬λ©΄ ν€λκ° λ΄μ©κ³Ό μλͺ» μ λ ¬λ©λλ€(μ€ν¬λ‘€ μμ§ μ€ν¬λ‘€ λ§λμ λλΉλ§νΌ).
νΉμλΌλ κ·Έ ν΄κ²°μ± μ μ°Ύμκ² μ΅λκΉ?
κ°μ¬ ν΄μ
μ 체 곡κ°: λλ μ€μ λ‘ μ²μλΆν° λ΄ μμ μ λ²μ μ λ§λ€μμ΅λλ€. μ΄ λΌμ΄λΈλ¬λ¦¬λ₯Ό κΈ°λ°μΌλ‘ νλ μ체 κ°μνκ° μμ΅λλ€. λ΄κ° μ΄λ κ² ν μ΄μ λ MacBookκ³Ό νΉμ Chrome νλκ·Έμμ μ€ν¬λ‘€ μ λλ©μ΄μ
μ΄ JSμ λ€λ₯Έ νμ΄λ°μΌλ‘ λ°μνλ λ¬Έμ κ° μκΈ° λλ¬Έμ
λλ€. ScrollSyncλ₯Ό μ¬μ©νλ €λ©΄ λ무 λ§μ μ λ¬ ν¨μ νΈμΆμ΄ νμνκ³ λ무 λλ Έμ΅λλ€. κΈ°λ³Έμ μΌλ‘ ν΅μ¬μ κ³ μ ν€λκ° μλ λΌμ΄λΈλ¬λ¦¬λ₯Ό λ€μ λ§λ€μ΄μΌ νμ΅λλ€(μ΄ μ€λ λμ μλΆλΆμμ λ§νλ―μ΄ position: sticky
μ¬μ©νμ§ μμμ΅λλ€. μΈμ κ°λ μ§κΈ κ°μ§κ³ μλ κ²μ μ
λ‘λν΄μΌ ν©λλ€).
μ¦, μ΄ λ¬Έμ λ₯Ό ν΄κ²°νλ λ°©λ²μ overflow: scroll
λ₯Ό μ¬μ©νμ¬ μ€ν¬λ‘€ λ§λλ₯Ό κ°μ μ€νν λ€μ ν΄λΉ ν¨λ©μ λ§μ§λ§ μ
μ μΆκ°νκ±°λ ref λ΄λΆμ 보μ΄μ§ μλ divλ₯Ό λ£κ³ μ€ν¬λ‘€ λ§λ ν¬κΈ°λ₯Ό μΈ‘μ νκ³ DOM λ
Έλλ₯Ό μμ ν©λλ€.
μ€ν¬λ‘€λ° μ€λ²λ μ΄λ₯Ό λ§λλ overflow-y: overlay
λ₯Ό μ¬μ©νμ΅λλ€. λΆννλ μΉν· λΈλΌμ°μ μμλ§ μλν©λλ€.
μκ² μ΅λλ€. μ 보 κ°μ¬ν©λλ€. μ€ν°ν€ ν€λλ λ§€μ° μΌλ°μ μΈ μꡬ μ¬νμ΄λ―λ‘ react-windowμ μ€ν°ν€ν 첫 λ²μ§Έ ν μ΅μ μ μΆκ°νλ κ²λ§μΌλ‘λ λ λ§μ κ²½μ°μ λ°μ κ°μνλ₯Ό λ체νκ² λ κ²μ λλ€. κ·Έλ κ² μκ°νμ§ μμ?
@ranneyd λ€μ ν λ² κ°μ¬λ립λλ€. κ·νμ μ κ·Ό λ°©μμ λ°λκ³ μ€ν¬λ‘€ λκΈ°νκ°
μ€ν¬λ‘€λ°μ μ¨κ²¨μ§ μ€λ²νλ‘λ 그리λ λ κ·Όμ²μμ μ λ ¬ λΆλμ μΌμΌν΅λλ€.
μ΄ λ¬Έμ λ₯Ό ν΄κ²°νλ λ°©λ²μ λν μ μ μ¬νμ΄ μμ΅λκΉ?
미리 κ°μ¬λ립λλ€
νν°μ λ¦μμ§λ§ leftRefμ ν νμ μΆκ°νκ³ μ€λ²νλ‘λ₯Ό μ¨κΉμΌλ‘ μ€μ νλ©΄ κΈ°λ³Έμ μΌλ‘ pbλ₯Ό ν΄κ²°ν μ μμ΅λλ€. (leftRef -> main Gridλ₯Ό λκΈ°ννμ§ μμλ λλλ‘ νμ΅λλ€.
const headerRef = React.useRef();
const leftRef = React.useRef();
return <Box classes={{
root:classes.tableContainer
}}>
<AutoSizer>
{({ height, width }) => (<>
{/*---------------- LAΒ TABLE -------------*/}
<Grid
columnCount={1000}
columnWidth={100}
height={height}
rowCount={1000}
rowHeight={35}
width={width}
onScroll={({ scrollLeft, scrollTop }) => {
if (leftRef.current) {
leftRef.current.scrollTo({ scrollTop });
}
if (headerRef.current) {
headerRef.current.scrollTo({ scrollLeft });
}
}}
>
{({ columnIndex, rowIndex, style }) => (
<Box style={style} classes={{root:classes.cell}}>
Item {rowIndex},{columnIndex}
</Box>
)}
</Grid>
{/*---------------- HEADER -------------*/}
<Grid
ref={headerRef}
outerElementType={React.forwardRef((props, ref) => (
<div ref={ref} {...props} style={{...props.style,position:"absolute",overflow:"hidden",top:0,right:0,left:150}} />
))}
columnCount={1001} /*columns count +1 for scroll problems*/
columnWidth={100}
height={60}
rowCount={1}
rowHeight={60}
width={width}
>
{({ columnIndex, rowIndex, style }) => (
<Box style={style} classes={{root:classes.headerCell}}>
Header {rowIndex},{columnIndex}
</Box>
)}
</Grid>
{/*---------------- LEFTΒ COL -------------*/}
<Grid
ref={leftRef}
outerElementType={React.forwardRef((props, ref) => (
<div ref={ref} {...props} style={{...props.style,position:"absolute",overflow:"hidden",top:60,left:0}} />
))}
columnCount={1}
columnWidth={150}
height={height}
rowCount={251} /** add 1 for scroll problems at the end */
rowHeight={140}
width={150}
>
{({ columnIndex, rowIndex, style }) => (
<Box style={style} classes={{root:classes.headerCell}}>
Left {rowIndex},{columnIndex}
</Box>
)}
</Grid>
</>)}
</AutoSizer>
</Box>
κ°μ₯ μ μ©ν λκΈ
κ·Έκ²μ μμ ν μλ―Έκ° μμ΅λλ€. μ μ κ°μ¬ν©λλ€! λλ κ·Έκ²μ μλ μμΌ°κ³ μ€μ λ‘ μ€μ νκΈ°κ° λ§€μ° μ½μ΅λλ€. λ무 μ¬μμ λ 립 μ€νν ν¨ν€μ§λ₯Ό 보μ¦νμ§ μμ΅λλ€. λ¬Έμμ μμΌ μλ μμ§λ§ κ·Έκ² λΉμ μ μ νλΌκ³ μκ°ν©λλ€. λμ€μ λ€λ₯Έ μ¬λμ΄ μ΄ λ¬Έμ λ₯Ό λ°κ²¬ν κ²½μ°λ₯Ό λλΉνμ¬ μμ μ€μΈ Code Sandbox μμ μ λν λ§ν¬λ₯Ό μ¬κΈ°μ λ¨κΈΈ κ²μ λλ€.
https://codesandbox.io/s/y3pyp85zm1
TLDR - ν€λ 그리λμ refλ₯Ό λ£κ³ λ³Έλ¬Έ 그리λμ λ£μ΅λλ€.