简体   繁体   English

reactjs-未捕获的TypeError:无法读取未定义的属性'map'

[英]reactjs - Uncaught TypeError: Cannot read property 'map' of undefined

I'm trying to use the contents of a json return to not only populate my list, but when creating a new list to allow the selection of a parent. 我试图使用json return的内容不仅填充我的列表,而且在创建新列表以允许选择父对象时使用。

I have the list coming up in my Navigation but when I click on "Create New List" it gives the following error: 我的导航中有该列表,但是当我单击“创建新列表”时,出现以下错误:

Uncaught TypeError: Cannot read property 'map' of undefined

Which occurs on this particular part of code: 这发生在代码的这一特定部分:

render: function() {
  var navNodes = this.props.data.map(function(nav) {
    return (
      React.createElement(NavItems, {name: nav.name, key: nav.id})
    );
  });
    return (
        React.createElement(Input, {
          label: "Parent List", 
          ref: "input", 
          value: this.state.value, 
          bsStyle: this.state.validationState, 
          hasFeedback: true, 
          help: this.state.hint, 
          onChange: this.handleChange, 
          type: "select"}, 
            this.renderPlaceholder(), 
            navNodes
        )
    );

Code: 码:

var Bootstrap = ReactBootstrap;
var Input = ReactBootstrap.Input;

var NavItems = React.createClass({
  render: function() {
    return (
      <option value={1}>{navNodes}</option>
    );
  }
});

var NavItem = React.createClass({
  render: function() {
    return (
      <li><a href="#">{this.props.name}</a></li>
    );
  }
});

var NavList = React.createClass({
  render: function() {
    var navNodes = this.props.data.map(function(nav) {
      return (
        <NavItem name={nav.name} key={nav.id}></NavItem>
      );
    });
    return (
      <ul className="nav">
        <li className="current"><a href="#"><i className="glyphicon glyphicon-home"></i> Lists</a></li>
        {navNodes}
      </ul>
    );
  }
});

var NewListButton = React.createClass({
  render: function() {
    return (
      <a {...this.props}
        href="javascript:;"
        role="button"
        className={(this.props.className || '') + ' btn'}
      />
    );
  }
});

var ListNameInput = React.createClass({
    getInitialState: function() {
        return {
            value: '',
            hint: null,
            validationState: null
        };
    },
    handleChange: function() {
        var newValue = this.refs.input.getValue(),
            hint = null,
            validationState = null,
            length = newValue.length;
        if (length > 2) { 
            validationState = 'success'; 
        } else {
            validationState = 'error'; 
            if (length) {
                hint = 'The name must be at least 3 characters long.';
            } else {
                hint = 'This value is required.';
            }
        }
        this.setState({
            value: newValue,
            hint: hint,
            validationState: validationState
        }); 
    },
    isValid: function() {
        return ('success' === this.state.validationState);
    },
    render: function() {
        return (
            <Input
              label='Name'
              ref='input'
              value={this.state.value}
              placeholder='Enter List Name'
              bsStyle={this.state.validationState}
              hasFeedback
              help={this.state.hint}
              onChange={this.handleChange}
              type='text' />
        );
    }
});

var ListDescriptionInput = React.createClass({
    getInitialState: function() {
        return {
            value: '',
            hint: null,
            validationState: null
        };
    },
    handleChange: function() {
        var newValue = this.refs.input.getValue(),
            hint = null,
            validationState = null,
            length = newValue.length;
        if (length > 2) { 
            validationState = 'success'; 
        } else {
            validationState = 'error'; 
            if (length) {
                hint = 'The description must be at least 3 characters long.';
            } else {
                hint = 'This value is required.';
            }
        }
        this.setState({
            value: newValue,
            hint: hint,
            validationState: validationState
        }); 
    },
    isValid: function() {
        return ('success' === this.state.validationState);
    },
    render: function() {
        return (
            <Input
              label='Description'
              ref='input'
              value={this.state.value}
              placeholder='Enter Description'
              bsStyle={this.state.validationState}
              hasFeedback
              help={this.state.hint}
              onChange={this.handleChange}
              type='text' />
        );
    }
});

var WidgetListSelect = React.createClass({
    getInitialState: function() {
        return {
            value: 0,
            hint: null,
            validationState: null
        };
    },
    handleChange: function() {
        var newValue = Number(this.refs.input.getValue()),
            hint = null,
            validationState = null;
        if (0 === newValue) {
            validationState = 'error';
            hint = 'You must select an parent list.';
        } else {
            validationState = 'success';
        }
        this.setState({
            value: newValue,
            hint: hint,
            validationState: validationState
        });
    },
    isValid: function() {
        return ('success' === this.state.validationState);
    },
    renderPlaceholder: function() {
        if (0 !== this.state.value)
            return null;
        // Show placeholder only prior to a value being selected
        return (
            <option value={0}>
                Please select a Parent List
            </option>
        );
    },
    render: function() {
      var navNodes = this.props.data.map(function(nav) {
        return (
          <NavItems name={nav.name} key={nav.id}></NavItems>
        );
      });
        return (
            <Input
              label='Parent List'
              ref='input'
              value={this.state.value}
              bsStyle={this.state.validationState}
              hasFeedback
              help={this.state.hint}
              onChange={this.handleChange}
              type='select'>
                {this.renderPlaceholder()}
                {navNodes}
            </Input>
        );
    }
});

var CreateNewListForm = React.createClass({
    handleSubmit: function() {
        var isValid = 
            !!(this.refs.nameInput.isValid()
                & this.refs.descriptionInput.isValid() 
                & this.refs.widgetlistSelect.isValid());
        if (isValid) {
            this.props.closeModal();
        } else {
            // Force validation of each element to show errors to user
            this.refs.nameInput.handleChange();
            this.refs.descriptionInput.handleChange();
            this.refs.widgetlistSelect.handleChange();
        }
    },
    render: function() {
        return (
            <div>
                <ListNameInput 
                  ref='nameInput' />
                <ListDescriptionInput 
                  ref='descriptionInput' />
                <WidgetListSelect 
                  ref='widgetlistSelect' />
                <Bootstrap.ButtonToolbar>
                    <Bootstrap.Button
                      onClick={this.handleSubmit}>
                        Save
                    </Bootstrap.Button>
                    <Bootstrap.Button
                      onClick={this.props.closeModal}>
                        Cancel
                    </Bootstrap.Button>
                </Bootstrap.ButtonToolbar>
            </div>
        );
    }
});

var NavBox= React.createClass({
  loadNavsFromServer: function() {
    $.ajax({
      url: "http://servername/api/widgetlists/?format=json",
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error("http://servername/api/widgetlists/?format=json", status, err.toString());
      }.bind(this)
    });
  },
  handleListSubmit: function(comment) {
    // TODO: submit to the server and refresh the list
  },
  getInitialState: function() {
    return {
      modalVisible: false,
      data: []};
  },
  onClick: function() {
      this.setState({modalVisible: true});
  },
  hideModal: function() {
      this.setState({modalVisible: false});
  },
  renderModal: function() {
      return (
          <Bootstrap.Modal 
            show={this.state.modalVisible}
            onHide={this.hideModal}>
              <Bootstrap.Modal.Body>
                  <CreateNewListForm 
                    closeModal={this.hideModal} />
              </Bootstrap.Modal.Body>
          </Bootstrap.Modal>
      );
  },
  componentDidMount: function() {
    this.loadNavsFromServer();
  },
  render: function() {
    return (
      <div className="col-md-2">
        <div className="sidebar content-box" style={{display: "block"}}>
            <NavList data={this.state.data} />
            {this.renderModal()}
            <Bootstrap.Button onClick={this.onClick}>
                Create New List
            </Bootstrap.Button>
         </div>
      </div>
    );
  }
});

module.exports = {
    NavBox: NavBox
}

You need a return value in getDefaultProps . 您需要在getDefaultProps返回一个值。

https://facebook.github.io/react/docs/reusable-components.html#default-prop-values https://facebook.github.io/react/docs/reusable-components.html#default-prop-values

getDefaultProps: function() {
    return {
      data: []
    };
  }

Also, it's good practice to define your prop types too: 另外,也是定义道具类型的好习惯:

propTypes: {
  data: React.PropTypes.array.isRequired
}

Whilst I'd avoid ES6/7 Class sugar as I'm not a fan of that specification (it's unhealthy for your JS mind like sugar), nevertheless, if you like it then their is also a way to define these as static property defaultProps . 虽然我会避免使用ES6 / 7类糖,因为我不喜欢该规范(但是像糖一样对您的JS头脑来说这是不健康的),但是,如果您喜欢它,那么它们也是将其定义为static属性defaultProps一种方式。

class Foo extends React.Component {
  static defaultProps = {
    bar: React.PropTypes.array.isRequired
  }
}

https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#es7-property-initializers https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#es7-property-initializers

this.props.data is not defined the first time render() is first called, and you are trying to call .map() on undefined, which results in an error. 首次调用render()时未定义this.props.data ,并且您尝试在undefined上调用.map() ,这会导致错误。

You should check that data is defined before calling map on it, and otherwise set navNodes to an empty array. 您应在调用map之前检查数据是否已定义,否则应将navNodes设置为空数组。

    const data = this.props.data;
    const navNodes = data ? data.map(...your function...) : [];

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

相关问题 未捕获到的TypeError:无法读取ReactJs中{Component} .render上未定义的属性“ map” - Uncaught TypeError: Cannot read property 'map' of undefined at {Component}.render in ReactJs reactjs Uncaught TypeError:无法读取未定义的属性&#39;map&#39; - reactjs Uncaught TypeError: Cannot read property 'map' of undefined React.js-未捕获的TypeError:无法读取未定义的属性&#39;then&#39; - Reactjs - Uncaught TypeError: Cannot read property 'then' of undefined 类型错误:无法读取未定义的属性“地图”| ReactJS - TypeError: Cannot read property 'map' of undefined | ReactJS ReactJS:TypeError:无法读取未定义的属性“map” - ReactJS: TypeError: Cannot read property 'map' of undefined TypeError:无法读取 reactJS 上未定义的属性“映射” - TypeError: Cannot read property 'map' of undefined on reactJS Reactjs:类型错误:无法读取未定义的属性“地图” - Reactjs : TypeError: Cannot read property 'map' of undefined ReactJS TypeError:无法读取未定义的属性“ map” - ReactJS TypeError: Cannot read property 'map' of undefined TypeError:无法读取 ReactJs 中未定义的属性“映射”? - TypeError: Cannot read property 'map' of undefined in ReactJs? TypeError:无法读取未定义的属性“地图”(REACTJS) - TypeError: Cannot read property 'map' of undefined (REACTJS)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM