2017-01-12 6 views
0

React Virtualized의 Collection 구성 요소를 사용하여 문제를 해결할 수 있다면 약간 혼란 스럽습니다. 내가하고있는 일을 설명하려고 노력할 것이다.React Virtualized : 동일한 고정 높이이지만 너비가 다른 셀을 가진 컬렉션

두 개의 목록/항목 모음을 표시하기 위해 React Virtualized를 사용하고 있습니다.

Collection where cells have same height & width

가 첫 번째 컬렉션 꽤 정직하고 쉽게 구현할 수 있었다 : 나는 같은 폭과 높이를 가진 항목이있는 첫 컬렉션을 완료했습니다. 이제 다양한 크기의 이미지가 포함 된 두 번째 컬렉션에서 작업하고 있습니다. 나는 세포가 같은 높이이지만 다른 폭을 가지기를 바란다. (이미지의 크기에 따라 다르다.)

Collection where cells have same height but different width

가상화를 달성 반응이 가능한가요 : 문제는 행이 항상 동일한 수의 셀이 없을 수도 있다는 것입니다? 그렇다면 어떻게 "cellSizeAndPositionGetter"에서 위치를 결정할 수 있습니까?

+0

짧은 nswer : 당신은 할 수 없습니다. 내가 생각할 수있는 해결 방법은 실제 행에있는 모든 셀을 분할하는 것이므로 행 1에는 처음 세 개의 이미지가 있고 행 2에는 네 개의 다음 이미지가 있습니다. 그런 다음 개별 셀이 아닌 행 자체를 가상화합니다. 일반적으로 가상화 된 목록 ("그리드"가 아닌 "목록")의 "의도적으로"제한됩니다. –

+0

나는 Sergiu가 말한 것에 동의합니다. 좀 더 추가하기 위해 보여준 최상위 콜렉션은 실제로 '컴포넌트'보다는 '그리드'여야합니다. 'Grid'는 사용하는 것이 더 효율적이고 더 간단합니다. 두 번째로 보여주는 것은 List 일 수 있지만 행 수를 계산하는 것은 약간 까다 롭습니다. – brianvaughn

+0

@brianvaughn 나는'Collection'과'Component'가 아니라고 생각하고 있나? 어쨌든, 나는 네가 무엇을 말하는지 보았다. 첫 번째 컬렉션을 위해'Grid '를 시도 할 것입니다. 두 번째 컬렉션의 경우 [CassetteRocks/react-infinite-scroller] (https://github.com/CassetteRocks/react-infinite-scroller)를 사용하여 종료했습니다. 여유 시간이있을 때 React Virtualized를 사용하여 두 번째 컬렉션을 다시 구현하려고합니다.나는 repo를 정말로 좋아하기 때문에! :) 귀하의 의견을 모두 주셔서 감사합니다. – Jooooooooohn

답변

1

최근에 고정 높이의 가변 폭 이미지 카드 행을 표시하기 위해 react-virtualizedList을 사용했으며 매우 효과적이었습니다.

ListrowRenderer은 이미지 카드 요소의 행 배열을 사용합니다. 즉, JSX처럼 반응 컴포넌트 배열의 배열입니다.

요소 너비와 화면 너비를 기반으로 행을 작성하는 방법에 대한 최종 기능은 cardsRows을 참조하십시오.

여기 보이는 방법은 다음과 같습니다

List rows layout

희망이 도움이! 내 코드의

일부 조각 :

import {AutoSizer, List} from 'react-virtualized'; 

...

updateDimensions() { 
    this.setState({ 
     screenWidth: window.innerWidth, 
    }); 
} 

componentDidMount() { 
    window.addEventListener("resize", this.updateDimensions); 
} 


componentDidUpdate(prevProps, prevState) { 
    const props = this.props; 
    const state = this.state; 

    if (JSON.stringify(props.imageDocs) !== JSON.stringify(prevProps.imageDocs) || state.screenWidth !== prevState.screenWidth) 
     this.setState({ 
      cardsRows: cardsRows(props, state.screenWidth), 
     }); 
} 


rowRenderer({key, index, style, isScrolling}) { 
    if (!this.state.cardsRows.length) 
     return ''; 
    return (
     <div id={index} title={this.state.cardsRows[index].length} key={key} style={style}> 
      {this.state.cardsRows[index]} 
     </div> 
    ); 
} 

...

render() { 
    return (
      <div style={styles.subMain}> 
       <AutoSizer> 
        {({height, width}) => (<List height={height} 
               rowCount={this.state.cardsRows.length} 
               rowHeight={164} 
               rowRenderer={this.rowRenderer} 
               width={width} 
               overscanRowCount={2} 
         /> 
        )} 
       </AutoSizer> 
      </div> 
    ); 
} 

...

const cardsRows = (props, screenWidth) => { 

    const rows = []; 
    let rowCards = []; 
    let rowWidth = 0; 
    const distanceBetweenCards = 15; 

    for (const imageDoc of props.imageDocs) { 
     const imageWidth = getWidth(imageDoc); 

     if (rowWidth + distanceBetweenCards * 2 + imageWidth <= screenWidth) { 
      rowCards.push(cardElement(imageDoc)); 
      rowWidth += distanceBetweenCards + imageWidth; 
     } 
     else { 
      rows.push(rowCards); 
      rowCards = []; 
      rowWidth = distanceBetweenCards; 
     } 
    } 
    if (rowCards.length) { 
     rows.push(rowCards); 
    } 
    return rows; 
}; 


const styles = { 
    subMain: { 
     position: 'absolute', 
     display: 'block', 
     top: 0, 
     right: 0, 
     left: 0, 
     bottom: 0, 
    } 
};