2017-11-25 10 views
0

반응 가상화를 기반으로 데이터 그리드 구성 요소를 개발 중입니다. 크기를 조정할 수있는 열이있는 고정 헤더가 있어야합니다. 머리글 셀 내용에 따라 머리글의 높이를 변경하고 싶습니다. 난 CellMeasurer을 사용하여 셀의 높이를 계산하고 헤더의 높이를 업데이트합니다.반응 가상화를 사용하여 동적 높이가있는 표 머리글을 구현하는 방법이 있습니까?

문제는 셀이 렌더링 된 후에 계산되므로 (afaik) 높이가 변경된 경우 forceUpdate을 헤더의 render 내부로 호출해야합니다. 여기

render 같이 (완벽한 예입니다 here) 모습입니다 :

render() { 
    const height = this._cache.rowHeight({ index: 0 }); 
    console.log('render', height, this.props.sizes); 
    setTimeout(() => { 
     if (height !== this._cache.rowHeight({ index: 0 })) { 
     console.log('forceUpdate', this._cache.rowHeight({ index: 0 })) 
     this.forceUpdate() 
     } 
    }, 0) 

    return (
     <Grid 
     ref={ref => this._grid = ref} 
     deferredMeasurementCache={this._cache} 
     width={1500} 
     height={height} 
     columnCount={5} 
     columnWidth={this.columnWidth} 
     rowCount={1} 
     rowHeight={this._cache.rowHeight} 
     cellRenderer={this.renderCell} 
     /> 
    ); 
    } 

그래서 forceUpdate 어떻게 피하는가하는 질문? 반응 가상화를 사용하여 동적 높이로 그리드 헤더를 구현하는 더 깨끗한 방법이 있습니까?

답변

0

합니다.

브라이언이 올바른 방향으로 지적 했으니, 놀라운 일과 지원을 해주신 브라이언에게 감사드립니다. 그것은 우리가 렌더링 최초의 후 헤더의 높이를 업데이트 할 수 있기 때문에 onSectionRendered 핸들러는 중요하다

그건 :

원래 codesandbox에서
_onSectionRendered = ({ rowOverscanStartIndex }) => { 
    if (rowOverscanStartIndex === 0) { 
     const height = this._cache.rowHeight({ index: 0 }); 

     if (height !== this.state.headerHeight) { 
     this.setState({ 
      headerHeight: height, 
     }); 
     } 
    } 
    } 

componentWillReceiveProps뿐만 아니라 중요 -이 어떤 구성 요소를 만드는 크기 조정 컬럼에 반응 :

componentWillReceiveProps(nextProps) { 
    if (nextProps.sizes !== this.props.sizes) { 
     this._cache.clearAll(); 
     console.log('recomputeGridSize'); 
     this._grid.recomputeGridSize(); 
     console.log('===', this._cache.rowHeight({ index: 0 })) 
    } 
    } 

무엇 실종되었다 componentDidUpdate입니다 :

componentDidUpdate() { 
    console.log('componentDidUpdate', 
     this._cache.rowHeight({ index: 0 })); 
    const height = this._cache.rowHeight({ index: 0 }); 

    if (height !== this.state.headerHeight) { 
     this.setState({ 
     headerHeight: height, 
     }); 
    } 
    } 

- 행의 높이가 헤더의 높이와 다른지 확인하고 필요한 경우 업데이트 할 수있는 방법입니다. componentDidUpdate은 초기 렌더링 후에 호출되지 않으므로 onSectionRendered이 도움이됩니다.

여분의 렌더링을 피할 수는 없지만 시간 초과 해킹보다 훨씬 더 깨끗합니다. 완전한 예제는 여기에 있습니다 : https://codesandbox.io/s/kor4vv6jqv.

1

render에 시간 제한을 설정하는 것은 좋은 생각이 아닙니다.

셀의 높이가 변경되면 (예 : rowHeight에서 반환 된 값) CellMeasurer will automatically notify the parent Grid입니다. 이 경우 Grid will automatically clear its position cache and re-render.

이 예제에서 다르게 수행하는 것은 Grid의 외부 높이를 셀 측정 높이와 같게 설정하는 것입니다. 이것은 일반적인 사용의 경우, 하지만 당신이없이 지원할 수없는과 같이 타이머 해킹 : 내가 대답으로 게시해야 같은 느낌

class XHeader extends React.Component { 
    _cache = new CellMeasurerCache({ 
    defaultHeight: 20, 
    fixedWidth: true, 
    }); 
    state = { 
    headerHeight: 20, 
    }; 
    renderCell = props => { 
    return (
     <HeaderCell 
     width={this.props.sizes[props.columnIndex]} 
     {...props} 
     cache={this._cache} 
     onMouseDown={this.props.onMouseDown} 
     /> 
    ); 
    } 
    columnWidth = ({ index }) => { 
    return this.props.sizes[index]; 
    } 
    render() { 
    return (
     <Grid 
     ref={ref => this._grid = ref} 
     deferredMeasurementCache={this._cache} 
     width={1500} 
     height={this.state.headerHeight} 
     columnCount={5} 
     columnWidth={this.columnWidth} 
     onSectionRendered={this._onSectionRendered} 
     rowCount={1} 
     rowHeight={this._cache.rowHeight} 
     cellRenderer={this.renderCell} 
     /> 
    ); 
    } 

    _onSectionRendered = ({ rowOverscanStartIndex }) => { 
    if (rowOverscanStartIndex === 0) { 
     const height = this._cache.rowHeight({ index: 0 }); 

     if (height !== this.state.headerHeight) { 
     this.setState({ 
      headerHeight: height, 
     }); 
     } 
    } 
    } 
} 
+0

브라이언, 협조 해 주셔서 감사합니다. 대답은 많은 도움이되었지만 달성하려는 노력과 조금 다릅니다. –