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

时间:2018-12-16 06:10:27

标签: javascript reactjs

我基本上是React的初学者。我有一个仪表板页面,其中显示一个React Table。我有一个自定义按钮,它将打开一个弹出页面,该弹出页面有一些复选框,允许我显示/隐藏那些React列。最初,此弹出页面中的所有复选框均设置为true。当我取消选中某个列时,该特定列将被禁用。

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);

这是我的子组件-在我的子页面(显示复选框的页面)中,我有4个主要功能-getCheckbox-创建复选框,handlecheckchild-处理取消选中事件,resetFilter和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);

我已经编写了所有主要功能(用于父级子页面中的操作,并将这些功能作为道具传递-从父页面到子页面的getCheckBox和resetFilter。

父页面的这一行出现错误-无法读取未定义的属性'length'

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

我基本上是React的初学者。因此,请帮助我了解导致错误的原因。

还告诉我是否可以在父页面中编写所有子功能吗?

编辑1-根据Code Maniac的回答

我将父代码更改为

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));
  }

我现在遇到错误-在resetFilter中,道具CustomizedView被标记为必需,但是其值为undefined

我在无限循环中收到错误和警告。

编辑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));
  }

我正在检查纱线的生成错误-未使用状态字段:“ filterItems”反应/未使用状态

1 个答案:

答案 0 :(得分:0)

您的代码中的问题在这里

const { items } = this.state.filterItems;

您正试图在数组(fillterItems是一个数组)中找到键(item属性),这就是为什么您不确定的原因。

这与下面的示例相同。

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

以及应该采取什么措施才能获得正确的输出。

const { filterItems } = this.state;

演示代码

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