簡體   English   中英

如何解構此反應組件中的 state 對象數組以使用單個字段數據

[英]How can I destructure a state array of objects in this react component to use individual field data

獲取后,我在組件的 state 的數組中有 96 個對象。 除了年份和某些情況下的月份之外,它們都是唯一的對象。 年份不能靜態設置,因為它顯然會在某個時候發生變化。 月份將從Integer轉換為String 我試圖 map 它,但我得到一個錯誤,說cannot read property map of undefined 但是,如果我console.log數據,我將得到包含 96 個對象的數組。 當我嘗試解構它時,我得到一個錯誤Invalid attempt to destructure non-iterable instance 我的主要目標是獲取年份並將其作為模板文字傳遞給headerName ,以便它作為下面所有數據的分組列加載。 並取月 integer 並將其轉換為該月的字符串我的該組件的代碼如下。

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;

這是返回的部分無法讀取未定義的屬性“地圖”

   <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。

沒有內置的 JS 方法可以將月份數字格式化為您可以自己構建的字符串:

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

您需要在 map 之前進行驗證。 要更加徹底地檢查它是否存在並且它是一個數組:

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>

你可以把當年的你的state,像這樣。

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

然后你可以通過this.state.currentYear過濾你的數據。

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

看來rowData 需要是 AgGridReact 的AgGridReact ,因此為AgGridReactrowData屬性寫入rowData={[data]}

編輯

如果您要根據年份過濾表中的數據(假設您想查看上一年的數據)添加onChange function changeYear將設置 state 並更改年份。 見下文。

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

當 state 更新時,數據將被重新過濾並僅反映新選擇的年份的數據。

至於月份,你可以像這樣把數字變成一個字符串。

   formatMonth = (x) =>{
      var months = ['January', 'February', 'March', ..., 'December']
      return months[x-1]
   }

您尚未在 state 變量中初始化 rowData。 我看到您已經在構造函數的 columnDefs 的子項中定義了 rowData。 這里發生了兩件事。

  1. 您已經在 function onGridReady 中初始化了 this.state.rowData
  2. 您在初始化之前訪問它。

因此,this.state.rowData 在初始化之前是未定義的,並且組件正在嘗試 map 超過未定義。 這就是為什么您收到錯誤Cannot read property 'map' of undefined 的原因。

可能的解決方案:

  1. 在使用它之前初始化構造函數中的變量。 this.state={... rowData:[]...}
  2. AgGridReact rowData={this.state.rowData}的 prop 更改為rowData={Array.isArray(this.state.rowData)? this.state.rowData: []} rowData={Array.isArray(this.state.rowData)? this.state.rowData: []}

我看到你在這個問題上問了很多事情。 這是其中的一部分。 更詳細地解釋您想要什么,或者可以將其划分為子問題。 然后很容易回答他們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM