2016-11-25 2 views
1

У меня есть интерактивный компонент внутри «реакционно-виртуализированного» списка, который действует на клики. Когда компонент кликается, ячейка преобразует, то есть изменения высоты.Как правильно использовать CellMeasurer?

Моя первая версия rowRenderer:

rowRenderer ({index, isScrolling, key, style}) { 
    let message = this.props.messages[index]; 

    return <Message key={message.id} text={message.text} /> 
} 

Когда сообщение будет нажата, появляется текстовое поле. Это изменяет высоту. Что происходит, так это то, что компонент отображает следующее сообщение.

Это происходит потому, что экземпляр Message отличается в пользовательском интерфейсе и в CellMeasurer, как вы можете увидеть:

<CellMeasurer 
    cellRenderer={ 
     // Here we return instance 1 
     ({ rowIndex, ...rest }) => this.rowRenderer({ index: rowIndex, ...rest }) 
    } 
    columnCount={1} 
    rowCount={messages.length} 
    > 

    {({ getRowHeight, resetMeasurementForRow }) => { 
    this.resetMeasurementForRow = resetMeasurementForRow; 

    return <List 
     height={height} 
     overscanRowCount={50} 
     rowCount={messages.length} 
     rowHeight={getRowHeight} 
     rowRenderer={this.rowRenderer} // Here we create another instance 
     width={width} 
     ref={(ref)=>{ 
      this.list = ref; 
     }} 
    /> 
    }} 
</CellMeasurer> 

экземпляр, созданный список будет, очевидно, содержать правильное состояние, но CellMeasurer не знает об этом состоянии.

Я протестировал следующий подход, но я очень сомневаюсь, что это правильный способ сделать это? Я просто кэширую экземпляр компонента пользовательского интерфейса самостоятельно:

rowRenderer ({index, isScrolling, key, style}) { 
    let message = this.props.messages[index]; 

    if(!this.componentCache[index]) { 
     this.componentCache[index] = <Message key={message.id} text={message.text} /> 
    } 

    return this.componentCache[index]; 
} 

Это исправляет эту проблему, но, вероятно, представляет собой множество других проблем. Каков правильный способ сделать это?

(я знаю, что с помощью Flux/Redux/глобальное состояние может исправить это, но мне интересно, есть некоторые фундаментальные реакции, виртуализированных особенность/аспект, который я здесь отсутствует.)

+0

По-видимому, я упускал из виду текущее ограничение с компонентами с состоянием. Это указано в документации. https://github.com/bvaughn/react-virtualized/blob/master/docs/CellMeasurer.md#limitations-and-performance-considerations – ooxio

ответ

2

Ответ на этот на самом деле в документации:

текущая реализация CellMeasurer создает клетки по требованию, меры их, а затем выбрасывает их. Будущие версии этого компонента могут попытаться клонировать или каким-либо другим способом совместно использовать ячейки с их родительской сеткой , чтобы повысить производительность. Однако до тех пор, пока не произойдет , будьте осторожны с использованием CellMeasurer для измерения компонентов с сохранением состояния. Поскольку ячейки созданы точно для измерения, они будут измеряться с их состоянием по умолчанию. Чтобы избежать этой проблемы для , используйте управляемые реквизиты (вместо состояния) для отображения ячейки .

Таким образом, нет другого решения, кроме обращения с состоянием вне компонента. На практике я зафиксировал его следующим образом:

rowRenderer ({index, isScrolling, key, style}) { 
    let message = this.props.messages[index]; 

    let selected = message.id === store.getState().selectedMessage; 

    return <Message key={message.id} text={message.text} selected={selected} /> 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^