简体   繁体   English

无法读取未定义错误的属性“长度”-ReactJS

[英]Cannot read property 'length' of undefined Error - ReactJS

I am basically a beginner in React. 我基本上是React的初学者。 I have a dashboard page where I display a React Table. 我有一个仪表板页面,其中显示一个React Table。 I have a customize button which will open a popup page, this popup page has some check boxes allows me to show/hide those React columns. 我有一个自定义按钮,它将打开一个弹出页面,该弹出页面有一些复选框,允许我显示/隐藏那些React列。 Initially all the check boxes in this popup page is set to true. 最初,此弹出页面中的所有复选框均设置为true。 When I uncheck a column that particular column get disabled. 当我取消选中某个列时,该特定列将被禁用。

图片

This is my parent component - the parent page is the page with the ReactTable, there are 10 columns now, not 8 as shown in the image. 这是我的父组件-父页面是带有ReactTable的页面,现在有10列,而不是图中的8列。

import React, { Component } from 'react';
import { connect } from 'react-redux';
import ReactTable from 'react-table';
import LoadingComponent from '../shared/loading/LoadingComponent';
import InputComponent from '../shared/input/InputComponent';
import { makeData } from '../../util/Utils';
import CustomizedView from './customized_view/CustomizedView';

import filter from '../../assets/svg/filter.svg';
import config from '../../../framework/config';
//import EnquiryDetails from './enquiry_details/enquiryDetails';

const searchIcon = config.assetUrl + '/table_filter/svg/search-icon.svg';


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

    this.state = {
      filterState: {},
      data: makeData(),
      searchText: '',
      isFilterOpen: false,
      isCustomizedOpen: false,
      isFiltered: false,
      isSearched: false,
      searchedTableData: [],
      filteredTableData: [],
      filterItems: [
        { id: 1, value: 'Col 1', isChecked: true },
        { id: 2, value: 'Col 2', isChecked: true },
        { id: 3, value: 'Col 3', isChecked: true },
        { id: 4, value: 'Col 4', isChecked: true },
        { id: 5, value: 'Col 5', isChecked: true },
        { id: 6, value: 'Col 6', isChecked: true },
        { id: 7, value: 'Col 7', isChecked: true },
        { id: 8, value: 'Col 8', isChecked: true },
        { id: 9, value: 'Col 9', isChecked: true },
        { id: 10, value: 'Col 10', isChecked: true },
      ],
    };
    this.handleFilterClickinv = this.handleFilterClickinv.bind(this);
    this.handleCustClickinv = this.handleCustClickinv.bind(this);
  }

  getTopBar() {
    return (
      <div className='top-bar-div'>
        <div className='heading-div'>Dashboard</div>
      </div>);
  }

  getFilterBar() {
    const searchIconImg = (<img src={searchIcon} alt="" />);
    if(this.state.isFiltered) table = this.state.filteredTableData;
    if(this.state.isSearched) table = this.state.searchedTableData;
    return (
      <div className='table-header-div' >
        <div className="filter-container-div">
        </div>
        <div className='search-enquiry-div'>
          <div className="search-container">
            <div className="search-input-container-div">
              <InputComponent
                height="41px"
                width="280px"
                inputClassName="order-filter-input"
                placeholder='Search'
                type="text"
                value={this.state.searchText}
                icon={searchIconImg}
                onChange={this.onSearch}
              />
            </div>
          </div>
        </div>
        <div className="filter-icon-div-main">
          <div className="custom-icon-div" onClick={() => { this.handleCustClickinv(); }}>
            <div className='customize-view-inventory'>Customized View </div>
          </div>
        </div>
      </div>);
  }

  getColumns() {
    const columns = [
        {
          id: "col16",
          Header: () => {
            return (
              <div>
                <div className="col1-heading">Col 1</div>
                <div className="col6-heading">Col 6</div>
              </div>
            );
          },
          accessor: d => {
            return (
              <div>
                <div className="col1">{d.firstName}</div>
                <div className="col6">{d.lastName}</div>
              </div>
            );
          },
          width: 200
        },
        {
          id: "col27",
          Header: () => {
            return (
              <div>
                <div className="col2-heading">Col 2</div>
                <div className="col7-heading">Col 7</div>
              </div>
            );
          },
          accessor: d => {
            return (
              <div>
                <div className="col2">{d.firstName}</div>
                <div className="col7">{d.lastName}</div>
              </div>
            );
          },
          width: 200
        },
        {
          id: "col38",
          Header: () => {
            return (
              <div>
                <div className="col3-heading">Col 3</div>
                <div className="col8-heading">Col 8</div>
              </div>
            );
          },
          accessor: d => {
            return (
              <div>
                <div className="col3">{d.firstName}</div>
                <div className="col8">{d.lastName}</div>
              </div>
            );
          },
          width: 200
        },
        {
          id: "col49",
          Header: () => {
            return (
              <div>
                <div className="col4-heading">Col 4</div>
                <div className="col9-heading">Col 9</div>
              </div>
            );
          },
          accessor: d => {
            return (
              <div>
                <div className="col4">{d.firstName}</div>
                <div className="col9">{d.lastName}</div>
              </div>
            );
          },
          width: 200
        },
        {
          id: "col510",
          Header: () => {
            return (
              <div>
                <div className="col5-heading">Col 5</div>
                <div className="col10-heading">Col 10</div>
              </div>
            );
          },
          accessor: d => {
            return (
              <div>
                <div className="col5">{d.firstName}</div>
                <div className="col10">{d.lastName}</div>
              </div>
            );
          },
          width: 200
        },
        {
          id: "col11",
          Header: "Col 11",
          columns: [
            {
              id: "scol11a",
              Header: "Sub Col 11a",
              accessor: d => {
                return d.firstName;
              },
              width: 80
            },
            {
              id: "scol11b",
              Header: "Sub Col 11b",
              accessor: d => {
                return d.firstName;
              },
              width: 80
            },
            {
              id: "scol11c",
              Header: "Sub Col 11c",
              accessor: d => {
                return d.firstName;
              },
              width: 80
            },
            {
              id: "scol11d",
              Header: "Sub Col 11d",
              accessor: d => {
                return d.firstName;
              },
              width: 80
            }
          ]
        },
        {
          id: "col12",
          Header: "Col 12",
          columns: [
            {
              id: "scol12a",
              Header: "Sub Col 12",
              accessor: d => {
                return d.firstName;
              },
              width: 80
            }
          ]
        },
        {
          id: "col13",
          Header: "Col 13",
          columns: [
            {
              id: "scol13a",
              Header: "Sub Col 13a",
              accessor: d => {
                return d.firstName;
              },
              width: 80
            },
            {
              id: "scol13b",
              Header: "Sub Col 13b",
              accessor: d => {
                return d.firstName;
              },
              width: 80
            },
            {
              id: "scol13c",
              Header: "Sub Col 13c",
              accessor: d => {
                return d.firstName;
              },
              width: 80
            },
            {
              id: "scol13d",
              Header: "Sub Col 13d",
              accessor: d => {
                return d.firstName;
              },
              width: 80
            }
          ]
        }
      ];

    // if(this.state.isDisabled) {
    //   columns.splice(0, 1);
    //   columns.splice(columns.length - 1, 1);
    // }
    return columns;
  }

  /*  function (item)*/

  getCheckBox(item) {
    return (
      <div>
        <input
          value={item.id}
          type='checkbox'
          checked={item.isChecked}
          onClick={(e) => { this.handleCheckChildElement(e); }}
        />
        {item.value}
      </div>);
  }

  handleCheckChildElement(event) {
    const { items } = this.state.filterItems;
    for (let i = 0; i < items.length; i = i + 1) {
      if(items[i].id === +event.target.value) {
        items[i].isChecked = !items[i].isChecked;
        break;
      }
    }
    this.setState({ filterItems: items });
    console.log('handleCheckChildElement : > Items : ' + JSON.stringify(filterItems));
  }

  handleFilterClickinv() {
    if(this.state.isCustomizedOpen) {
      this.setState({ isCustomizedOpen: false });
    }
    const currentState = this.state.isFilterOpen;
    this.setState({ isFilterOpen: !currentState });
  }

  handleCustClickinv() {
    if(this.state.isFilterOpen) {
      this.setState({ isFilterOpen: false });
    }
    const currentState = this.state.isCustomizedOpen;
    this.setState({ isCustomizedOpen: !currentState });
  }

  resetFilter() {
    const { items } = this.state.filterItems;
    console.log("In resetFilter this.state.filterItems : " + JSON.stringify(this.state.filterItems));
    console.log("In resetFilter : " + items);
    for (let i = 0; i < items.length; i = i + 1) {
      items[i].isChecked = true;
    }
    this.setState({ filterItems: items });
    console.log('Reset filter : > Items : ' + JSON.stringify(filterItems));
  }

  render() {
    const { data } = this.state;
    return (
      <div className='dashboard-body-container'>
        <div className='hide'> {this.state.activeStepId}</div>
        {this.getTopBar()}
        {this.state.isCustomizedOpen &&
          <CustomizedView
            // items={filterItems}
            getCheckBox={(item) => { this.getCheckBox(item); }}
            // handleCheckChildElement={(event) => { this.handleCheckChildElement(event); }}
            resetFilter={this.resetFilter()}
          />}
        <div className='whiteBackground'>
          {this.getFilterBar()}
          <div>
            {this.state.isLoading &&
            <LoadingComponent />
          }
          </div>
          <div>
            <ReactTable
              data={data}
              columns={this.getColumns()}
              showPagination
              defaultPageSize={10}
            />
          </div>
        </div>
      </div>
    );
  }
}

Dashboard.propTypes = {
};

function mapStateToProps(state) {
  return {
    auth: state.auth
  };
}

export default connect(mapStateToProps)(Dashboard);

This is my child component - in my child page (the page in which checkboxes are displayed) I have 4 major functions - getCheckbox - to create checkbox, handlecheckchild - handle the check uncheck events, resetFilter and applyFilter. 这是我的子组件-在我的子页面(显示复选框的页面)中,我有4个主要功能-getCheckbox-创建复选框,handlecheckchild-处理检查取消选中事件,resetFilter和applyFilter。 I have not still finished the code of applyFilter. 我还没有完成applyFilter的代码。

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { ActionCreators } from '../../../actions';
import ButtonComponent from '../../common/button/ButtonComponent';

class CustomizedView extends Component {
  constructor(props) {
    super(props);
    this.state = {
    };
  }

  render() {
    const { items } = this.state;
    return (
      <div className='DashboardFilter-container-custom' >
        <div className='bottomBar'>
          <ButtonComponent
            text='Apply'
            className='activeButton filterMargin-div'
            width='100'
            display='inline-block'
            // onClick={() => { this.props.applyFilter(); }}
          />
          <ButtonComponent
            text='Reset View'
            className='greyedButton clear-div-filter'
            width='100'
            display='block'
            marginTop='60'
            onClick={() => { this.props.resetFilter(); }}
          />
        </div>
        <div>
          <div className='column-points-text'>
            <span> Columns </span>
          </div>
          <div className="App">
            {items.map((item) => {
                return this.props.getCheckBox(item);
            })}
          </div>
        </div>
      </div>
    );
  }
}

CustomizedView.propTypes = {
  // items: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  getCheckBox: PropTypes.func.isRequired,
  // handleCheckChildElement: PropTypes.func.isRequired,
  resetFilter: PropTypes.func.isRequired
};

CustomizedView.defaultProps = {
};

function mapStateToProps(state) {
  return {
    auth: state.auth
  };
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(ActionCreators, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(CustomizedView);

I have written all the major functions (for operations in child page in my parent and passing those functions as props - getCheckBox and resetFilter from parent page to child page. 我已经编写了所有主要功能(用于父级子页面中的操作,并将这些功能作为道具传递-从父页面到子页面的getCheckBox和resetFilter。

I am getting error in the this line of my parent page - Cannot read property 'length' of undefined 我的父页面的这一行出现错误-无法读取未定义的属性“ length”

for (let i = 0; i < items.length; i = i + 1) {

I am basically a beginner in React. 我基本上是React的初学者。 So please help to me understand what is causing the error. 因此,请帮助我了解导致错误的原因。

Also tell me whether it is okay to write all child functions in parent page? 还告诉我是否可以在父页面中编写所有子功能?

Edit 1 - According to Code Maniac's answer 编辑1-根据Code Maniac的回答

I changed my code in parent to 我将父代码更改为

handleCheckChildElement(event) {
    const { filterItems } = this.state;
    for (let i = 0; i < filterItems.length; i = i + 1) {
      if(filterItems[i].id === +event.target.value) {
        filterItems[i].isChecked = !filterItems[i].isChecked;
        break;
      }
    }
    this.setState({ filterItems });
    console.log('handleCheckChildElement : > Items : ' + JSON.stringify(filterItems));
  }

  resetFilter() {
    const { filterItems } = this.state;
    for (let i = 0; i < filterItems.length; i = i + 1) {
      filterItems[i].isChecked = true;
    }
    this.setState({ filterItems });
    console.log('Reset filter : > Items : ' + JSON.stringify(filterItems));
  }

I am now getting error - The prop resetFilter is marked as required in CustomizedView , but its value is undefined . 我现在遇到错误-道具resetFilterCustomizedView标记为必需,但其值undefined

I am getting error and warning in an infinite loop. 我在无限循环中收到错误和警告。

Edit 2 - if change my code like this 编辑2-如果像这样更改我的代码

handleCheckChildElement(event) {
    const { items } = this.state;
    for (let i = 0; i < items.length; i = i + 1) {
      if(items[i].id === +event.target.value) {
        items[i].isChecked = !items[i].isChecked;
        break;
      }
    }
    this.setState({ filterItems: items });
    console.log('handleCheckChildElement : > Items : ' + JSON.stringify(filterItems));
  }

  resetFilter() {
    const { items } = this.state;
    for (let i = 0; i < items.length; i = i + 1) {
      items[i].isChecked = true;
    }
    this.setState({ filterItems: items });
    console.log('Reset filter : > Items : ' + JSON.stringify(filterItems));
  }

I am geeting yarn build error - Unused state field: 'filterItems' react/no-unused-state 我正在检查毛线生成错误-未使用状态字段:“ filterItems” react / no-unused-state

Well problem in you code is here 好吧,您代码中的问题在这里

const { items } = this.state.filterItems;

You're trying to find a key ( item property ) in array ( fillterItems is an array ) which is why you're getting undefined . 您正在尝试在数组(fillterItems是一个数组)中找到键(item属性),这就是为什么您不确定的原因。

This will be same as below example. 这将与下面的示例相同。

 let a = [{v:1},{2:2}]; let {items} = a; console.log(items) 

And what you should do instead to get proper output. 而应该怎么做才能获得正确的输出。

const { filterItems } = this.state;

Demo code 演示代码

 let a = { items : [{v:1},{2:2}], itemstemp : "temp" } let {items} = a; console.log(items) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM