Как я могу деструктурировать массив состояний объектов в этом реагирующем компоненте, чтобы использовать данные отдельных полей - PullRequest
1 голос
/ 28 октября 2019

У меня 96 объектов в массиве в состоянии компонента после выборки. Все они являются уникальными объектами, за исключением года, а в некоторых случаях и месяца. Год не может быть установлен статически, потому что он, очевидно, изменится в какой-то момент. Месяцы будут конвертированы из Integer в String. Я пытался сопоставить его, но я получаю сообщение об ошибке cannot read property map of undefined. Однако, если я console.log данных, это я получу массив с 96 объектами. И когда я пытаюсь его разрушить, я получаю ошибку Invalid attempt to destructure non-iterable instance. Моя главная цель - взять год и передать его как шаблонный литерал в headerName, чтобы он загружался в виде сгруппированного столбца для всех данных ниже. И взять целое число месяца и преобразовать его в строку этого месяца Мой код для этого компонента приведен ниже.

import React, { Component } from "react";
import { AgGridReact } from "ag-grid-react";

class ColumnGroups extends Component {
  constructor(props) {
    super(props);

    this.state = {
      columnDefs: [
        {
          headerName: "Year",
          field: "year",
          children: [
            {
              headerName: "Month",
              field: "month",
              width: 150,
              children: [
                  {
                  headerName: "Sold",
                  field: "sales",
                  width: 150
              },
              {
                  headerName: "Return",
                  field: "returns",
                  width: 150
              },
              {
                  headerName: "RMA%",
                  field: "rma",
                  width: 150
              }
                  ]
              }

              ],
              defaultColDef: {
                  editable: false,
                  sortable: true,
                  resizable: true,
                  filter: true
                },
                rowSelection: "multiple",
                rowGroupPanelShow: "always",
                pivotPanelShow: "always",
                paginationPageSize: 10,
                paginationNumberFormatter: function(params) {
                  return "[" + params.value.toLocaleString() + "]";
                },
                rowData: []


          }

      ],
  }

  }
  onGridReady = params => {
    this.gridApi = params.api;
    this.gridColumnApi = params.columnApi;

    const httpRequest = new XMLHttpRequest();
    const updateData = data => {
      this.setState({ rowData: data });
      params.api.paginationGoToPage(4);
    };

    httpRequest.open(
      "GET",
      "http://localhost:5000/api/salessummary"
    );
    httpRequest.send();
    httpRequest.onreadystatechange = () => {
      if (httpRequest.readyState === 4 && httpRequest.status === 200) {
        updateData(JSON.parse(httpRequest.responseText));
      }
    };
  };

  onPageSizeChanged(newPageSize) {
    var value = document.getElementById("page-size").value;
    this.gridApi.paginationSetPageSize(Number(value));
  }

render() {
  {console.log(this.state.rowData)}
    return (
        <div>
            <div>
                <div 
    className="ag-theme-balham"
    style={{ 
    height: '500px', 
    width: '100%' }} 
  >
      <div className="test-header">
        Page Size:
        <select onChange={this.onPageSizeChanged.bind(this)} id="page-size">
          <option value="10" selected="">
            10
          </option>
          <option value="100">100</option>
          <option value="500">500</option>
          <option value="1000">1000</option>
        </select>
      </div>
    <AgGridReact
      columnDefs={this.state.columnDefs}
      rowData={this.state.rowData}
      autoGroupColumnDef={this.state.autoGroupColumnDef}
      defaultColDef={this.state.defaultColDef}
      suppressRowClickSelection={true}
      groupSelectsChildren={true}
      debug={true}
      rowSelection={this.state.rowSelection}
      rowGroupPanelShow={this.state.rowGroupPanelShow}
      pivotPanelShow={this.state.pivotPanelShow}
      enableRangeSelection={true}
      pagination={true}
      paginationPageSize={this.state.paginationPageSize}
      paginationNumberFormatter={this.state.paginationNumberFormatter}
      onGridReady={this.onGridReady}
      >

    </AgGridReact>
  </div>
            </div>
        </div>

    )
}
}
export default ColumnGroups;

вот часть, которая возвращается. Не удается прочитать свойство 'map' из неопределенного

   <div>
           {
    this.state.rowData.map(data => <div>{data.year}</div> )
  }
</div>

Данные приведены ниже

{
"year": 2019,
"month": 4,
"productStyle": "zzzzz",
"sales": 1,
"returns": 0,
"rma": 0
},

Каждый годточно такой же. Картография возвращает 96 лет, 95 из них мне не нужны. И это изменится, я хочу, чтобы это было динамичным для полевого года. И мне нужно получить доступ к месяцу, чтобы я мог изменить integer на string 3 в апреле и т. Д.

Ответы [ 3 ]

2 голосов
/ 28 октября 2019

Не существует встроенного метода JS для форматирования чисел месяца в строки, которые вы можете создать самостоятельно:

numToMonth(n){
    switch(n){
        case 1:
           return 'Jan'
        //... all months
        default:
           return 'Dec'
        }
}

Необходимо проверить перед отображением. Чтобы быть более тщательным, проверьте, существует ли он и является ли он массивом:

render(){
    if(this.state.rowData && Array.isArray(this.state.rowData)){
        var items = this.state.rowData
    }
    return(
        <div>
            {items && items.map(item => <div>{item.Year}</div> )}
        </div>
    )
  }
}

, если вам нужен один элемент на основе текущего года, используйте команду:

render(){
    if(this.state.rowData && Array.isArray(this.state.rowData)){
        var item = this.state.rowData.find(data => data.year === new Date().getFullYear )
    }

    return(
        <div>
            {item && `${item.year} - ${this.numToMonth(item.month)}` }
        </div>
    )
}

, если вам нужно много элементовна основе фильтра текущего года:

render(){
    if(this.state.rowData && Array.isArray(this.state.rowData)){
        var items = this.state.rowData.filter(data => data.year === new Date().getFullYear )
    }

    return(
        <div>
            {item && items.map(items=> <div>{item.year} - {this.numToMonth(item.month)} </div>})
        </div>
    )
}

Если у всех один и тот же год, и вам нужны несколько номеров месяцев в виде строк:

render(){
    if(this.state.rowData && Array.isArray(this.state.rowData)){
        var items = this.state.rowData
    }
    return(
        <div>
            {items && items[0].year}
            {items && items.map(item => <div>{this.numToMonth(item.month)}</div> )}
        </div>
    )
  }
}

Запускаемый фрагмент последнего примера:

class SomeComponent extends React.Component {
  state={
    rowData:[
      {year:1988,month:1},
      {year:1988,month:3},
      {year:1988,month:2},
      {year:1988,month:1},
    ]
  }
  numToMonth(n){
    switch(n){
        case 1:
           return 'Jan'
        case 2:
           return 'Feb'
        case 3:
           return 'March'
        //... all months
        default:
           return 'Dec'
        }
  }
  render(){
    if(this.state.rowData && Array.isArray(this.state.rowData)){
        var items = this.state.rowData
    }
    return(
        <div>
            {items && items[0].year}
            {items && items.map(item => <div>{this.numToMonth(item.month)}</div> )}
      </div>
    )
  }
}

ReactDOM.render(
  <SomeComponent />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

<div id="react"></div>
1 голос
/ 28 октября 2019

Вы не инициализировали rowData в своей переменной состояния. Я вижу, что вы определили rowData внутри дочернего элемента columnDefs в конструкторе. Здесь происходят две вещи.

  1. Вы инициализировали this.state.rowData внутри функции onGridReady .
  2. Вы обращаетесь к ней раньше инициализировано .

Таким образом, this.state.rowData не определено до инициализации, и компонент пытается отобразить на неопределенное. Вот почему вы получаете сообщение об ошибке Не удается прочитать свойство 'map' из неопределенного .

Возможные решения:

  1. Инициализировать переменную внутри Конструктор перед его использованием. this.state={... rowData:[] ...}.
  2. Изменить реквизит AgGridReact rowData={this.state.rowData} на rowData={Array.isArray(this.state.rowData)? this.state.rowData : []}

Я вижу, что вы задали много вопросов в этом вопросе. Это одна часть этого. Объясните более подробно, что вы хотите или, возможно, разделите это на подзадачи. Тогда было бы легко ответить на них.

1 голос
/ 28 октября 2019

Вы можете указать текущий год для своего штата, например так.

state = {
   ...
   currentYear: new Date().getFullYear();
}

Затем вы можете отфильтровать ваши данные по this.state.currentYear.

var data = this.state.rowData.find((x)=>{return x.year === this.state.currentYear})

Появляется rowData должен быть массивом для AgGridReact, поэтому напишите rowData={[data]} для AgGridReact 'rowData prop.

Edit

Если вы собираетесь фильтровать эти данные в таблице на основе года (скажем, вы хотите посмотреть данные предыдущего года), добавьте функцию onChange changeYear, которая установит состояние и изменит год. См. Ниже.

changeYear = (year) =>{
    this.setState({
        currentYear: year
    })
}

При обновлении состояния данные будут повторно отфильтрованы и будут отображать только данные для нового выбранного года.

Что касается месяца, вы можете указать число. в строку, как это.

   formatMonth = (x) =>{
      var months = ['January', 'February', 'March', ..., 'December']
      return months[x-1]
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...