2017-02-22 26 views
1

Я пытаюсь использовать this example разработчиками React, чтобы создать фильтр поиска для таблицы.React fixed-data-table: Uncaught TypeError: this._dataList.getSize не является функцией

У меня есть таблица, работающая нормально с данными из моего бэкэнда статически. Я взял массив для «выборочных» данных, чтобы получить работу поиска. Но мне сложно скрыть время, когда они используют «поддельные данные», чтобы заполнить их таблицу как seen here, в отличие от «всего лишь» заполнения его тестовым массивом, как я хочу.

Вот мой исходный код. Я хочу фильтровать через столбец «firstName», как и в примере Facebook (для простоты). Ошибка возникает, когда вызывается getSize() ... Но я подозреваю, что проблема - это что-то еще.

class DataListWrapper { 
    constructor(indexMap, data) { 
     this._indexMap = indexMap; 
     this._data = data; 
    } 

    getSize() { 
     return this._indexMap.length; 
    } 

    getObjectAt(index) { 
     return this._data.getObjectAt(
      this._indexMap[index], 
     ); 
    } 
} 

class NameTable extends React.Component { 
    constructor(props) { 
     super(props); 

     this.testDataArr = []; // An array. 
     this._dataList = this.testDataArr; 

     console.log(JSON.stringify(this._dataList)); // It prints the array correctly. 


     this.state = { 
      filteredDataList: new DataListWrapper([], this._dataList) 
     }; 

     this._onFilterChange = this._onFilterChange.bind(this); 
    } 

    _onFilterChange(e) { 
     if (!e.target.value) { 
      this.setState({ 
       filteredDataList: this._dataList, 
      }); 
     } 

     var filterBy = e.target.value; 
     var size = this._dataList.getSize(); 
     var filteredIndexes = []; 
     for (var index = 0; index < size; index++) { 
      var {firstName} = this._dataList.getObjectAt(index); 
      if (firstName.indexOf(filterBy) !== -1) { 
       filteredIndexes.push(index); 
      } 
     } 

     this.setState({ 
      filteredDataList: new DataListWrapper(filteredIndexes, this._dataList), 
     }); 
    } 

    render() { 

     var filteredDataList = this.state.filteredDataList; 


     if (!filteredDataList) { 
      return <div>Loading table.. </div>; 
     } 

     var rowsCount = filteredDataList.getSize(); 



     return (
      <div> 
       <input onChange={this._onFilterChange} type="text" placeholder='Search for first name.. ' /> 
       {/*A table goes here, which renders fine normally without the search filter. */} 
      </div> 
     ); 
    } 
} 

export default NameTable 
+0

Извините, что сказал, что, но вы делаете это неправильно. Прежде всего, очень сложно хранить объект в состоянии, когда вы можете сохранить его в своем классе. Вы должны хранить в своих состояниях: dataListLoaded. Когда ваш datalist загружен, вы должны сделать setState (dataListLoaded: true), чтобы перезагрузить ваш компонент. – Kornflexx

+0

Достаточно честно, я относительно новичок в области React и front-end. Если бы вы могли представить пример кода, о котором вы упоминаете, я бы хотел его протестировать. – cbll

+0

Чтобы найти хорошие способы кода в es6 и в реагировании, я смотрю на это: https://github.com/ryanmcdermott/clean-code-javascript и некоторый исходный код хорошей библиотеки, например material-ui – Kornflexx

ответ

1

Ваша проблема в _onFilterChange метод.

Вы делаете это:

var size = this._dataList.getSize(); 

this._dataList это просто массив, поэтому GETSIZE() не существует в этом объекте.

Если я не misundertanding вы должны сделать это:

var size = this.state.filteredDataList.getSize(); 

То же самое случилось внутри цикла, вы делаете это:

var {firstName} = this._dataList.getObjectAt(index); 

, когда вы должны сделать это:

var {firstName} = this.state.filteredDataList.getObjectAt(index); 

Ваш метод _onFilterChange должен выглядеть примерно так:

_onFilterChange(e) { 
    if (!e.target.value) { 
     this.setState({ 
     filteredDataList: this._dataList, 
     }); 
    } 

    var filterBy = e.target.value; 
    //var size = this._dataList.getSize(); 
    var size = this.state.filteredDataList.getSize(); 
    var filteredIndexes = []; 
    for (var index = 0; index < size; index++) { 
     //var {firstName} = this._dataList.getObjectAt(index); 
     var {firstName} = this.state.filteredDataList.getObjectAt(index); 
     if (firstName.indexOf(filterBy) !== -1) { 
     filteredIndexes.push(index); 
     } 
    } 

    this.setState({ 
     filteredDataList: new DataListWrapper(filteredIndexes, this._dataList), 
    }); 
} 
0

getSize() и getObjectAt() могут быть вызваны только для объекта данных, который реализует эти методы, такие как объект DataListWrapper.

Если вы передаете простой массив данных для рендеринга(), то он не предлагает методы getSize() и getElementAt(), и вызов методов будет терпеть неудачу.

Оригинальная демонстрация работает, потому что данные FakeObjectDataListStore представляют собой объект («FakeObjectDataListStore»), который реализует методы getSize и getObjectAt).

Простейшая интеграция заключается в том, чтобы удостовериться, что данные, переданные в, являются объектом, предлагающим эти методы. Основанный в моем случае на «examples/FilterExample», я нашел, что самая простая интеграция (после борьбы со многими плохими) заключалась в том, чтобы превратить существующие «помощники/FakeObjectDataListStore.js» в мои собственные помощники/ObjectDataListStore.js (или выбрал ваше имя) таким образом сохраняя существующую структуру обертывания метода и параметры размера во всем дизайне. Затем я просто заменил вызовы на «поддельный» компонент ссылками на мои собственные неинтегрированные локальные массивы строк списка. Вы можете расположить ваши локальные данные как статические или динамически загруженные из любой используемой вами среды базы данных. Затем было легко модифицировать метод _setFiltered() для фильтрации на чем-то еще, чем «firstName».

Прохладная вещь с FixedDataTable - это возможность просматривать большие списки, и что разработчик может создавать собственные пользовательские рендеринги ячеек, например, отображая индикатор выполнения, кнопку или меню в любом месте строки списка.

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

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