Почему не работает скролл элемента?

350
09 августа 2017, 22:01

Работаю с данной компонентой. Все отрисовывается хорошо, выделение итемов работает,но почему-то нет скролла.Выводится только 21 итем и все.Хотя если регулировать высоту блока,то видно.что в массиве 500 итемов.В чем может быть ошибка?

export default class Example extends Component {
    constructor(props) {
        super(props);
        if (_items.length === 0) {
            for (let i = 0; i < 200; i++) {
                _items.push({
                    key: i,
                    name: 'Item ' + i,
                    value: i
                });
            }
        }
        this._selection = new Selection({
            onSelectionChanged: () => this.setState({ selectionDetails: this._getSelectionDetails() })
        });
        this.state = {
            items: _items,
            selectionDetails: this._getSelectionDetails()
        };
    }
    render(){
        let {
            items,
            selectionDetails
        } = this.state;
        return (
            <div>
                    <MarqueeSelection selection={ this._selection } style={{'overflow':'auto'}}>
                        <DetailsList
                            items={ items }
                            columns={ _columns }
                            setKey='set'
                            layoutMode={ DetailsListLayoutMode.fixedColumns }
                            selection={ this._selection }
                            selectionPreservedOnEmptyClick={ true }
                            onItemInvoked={ (item) => alert(`Item invoked: ${item.name}`) }
                        />
                    </MarqueeSelection>
                </div>
        );
    }
    _getSelectionDetails = () => {
        let selectionCount = this._selection.getSelectedCount();
        switch (selectionCount) {
            case 0:
                return 'No items selected';
            default:
                return `${selectionCount} items selected`;
        }
    };
}
Answer 1

1) Чтобы была прокрутка надо style={{'overflow':'auto'}} передать в div, а не в MarqueeSelection

2) По поводу динамической подгрузки айтемов:

Первое, что нам нужно сделать - это передать в div обработчик onScroll и получить ссылку на его node с помощью ref:

<div
   onScroll={this.handleScroll}
   ref={el => this.scroll = el}>

Далее получим ссылку на сам список и закешируем его высоту:

componentDidMount(){
    this.detailList=this.scroll.childNodes[0];
    this.scrollHeight = this.scroll.clientHeight
}

Теперь нам надо получить предельное значение scrollTop по достижению которого мы будем подгружать айтемы. Первое, что скорее всего прийдет в голову - это получать его в componentDidUpdate, но это ошибочное решение, т.к. DetailsList - это ассинхронный компонент и сразу после того как наш компонент примонтируется, там айтемов не будет и его высота будет 0. Поэтому воспользуемся onDidUpdate самого DetailsList. Стоит заметить, что вызывается он не только при апдейте, но и при первом рендере айтемов.

<DetailsList
   onDidUpdate={this.handleDetailListUpdate}

И сам обработчик:

handleDetailListUpdate=()=>{
    this.maxScrollTop=this.detailList.clientHeight-this.scrollHeight-100;
}

Ну и наконец-то обработчик скролла:

handleScroll=()=>{
    if (this.scroll.scrollTop>this.maxScrollTop){
        this.setState({
            items: this.state.items.concat(this.getItems()),
        });
    }
}

Функция getItems() для теста:

startNum = 0;
getItems(){
    const items = [];
    const finishNum = this.startNum + 50;
    for (let i = this.startNum; i<finishNum; i++) {
        items.push({
            key: i,
            name: 'Item ' + i,
            value: i
        });
    }
    this.startNum += 50;
    return items;
}

Ну и не забудем получить первую порцию айтемов в конструкторе:

constructor(props) {
    super(props);
    this.state = {
        items: this.getItems(),
        selectionDetails: this._getSelectionDetails()
    };
}

Вот и все.

Ну и на всякий случай код всего компонента:

export default class Example extends Component {
constructor(props) {
    super(props);
    this._selection = new Selection({
        onSelectionChanged: () => this.setState({ selectionDetails: this._getSelectionDetails() })
    });
    this.state = {
        items: this.getItems(),
        selectionDetails: this._getSelectionDetails()
    };
}
startNum = 0;
getItems(){
    const items = [];
    const finishNum = this.startNum + 50;
    for (let i = this.startNum; i<finishNum; i++) {
        items.push({
            key: i,
            name: 'Item ' + i,
            value: i
        });
    }
    this.startNum += 50;
    return items;
}
componentDidMount(){
    this.detailList=this.scroll.childNodes[0];
    this.scrollHeight = this.scroll.clientHeight
}
handleScroll=()=>{
    if (this.scroll.scrollTop>this.maxScrollTop){
        this.setState({
            items: this.state.items.concat(this.getItems()),
        });
    }
}
handleDetailListUpdate=()=>{
    this.maxScrollTop=this.detailList.clientHeight-this.scrollHeight-100;
}
render(){
    let {
        items,
        selectionDetails
    } = this.state;
    return (
        <div
            style={{height:'800px', overflow:'auto' }}
            onScroll={this.handleScroll}
            ref={el => this.scroll = el}>
                <MarqueeSelection selection={ this._selection }>
                    <DetailsList
                        onDidUpdate={this.handleDetailListUpdate}
                    />
                </MarqueeSelection>
            </div>
    );
}
_getSelectionDetails = () => {
    let selectionCount = this._selection.getSelectedCount();
    switch (selectionCount) {
        case 0:
            return 'No items selected';
        default:
            return `${selectionCount} items selected`;
    }
};

}

READ ALSO
Исключение элемента из выборки

Исключение элемента из выборки

Как селектором :not или методом not() исключить из обернутого набора вложенный элемент? Есть такая структура:

322
Как реализовать MVC на Express.js?

Как реализовать MVC на Express.js?

Никак не могу разобраться, как реализовать модели в Expressjs? Подскажите ресурсы, где описано, как это сделать

326
Сохранение данных об удалении

Сохранение данных об удалении

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

330