最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Uncaught TypeError: Cannot read property of null, removing element from array javascript - Stack Overflow

programmeradmin0浏览0评论

I am trying to remove an element from an array when the onClick on the remove button is called, when the button is clicked I am getting Uncaught TypeError: Cannot read property 'name' of null

Why am I getting this error?

removeData(key) {
  console.log(key);
  const data = this.state.data;
  data[key] = null;
  this.setState({ data });
}

renderData(key){
    const user = this.props.data[key];
    console.log(user.name);
    console.log(user.id);
    return(
      <div key={key}>
          <li>  <strong> Name: </strong>  {user.name},
          <strong>  ID: </strong> {user.id} </li>
          <button onClick={() => this.props.removeData(key)}> Remove </button>
      </div>
    )
}

I am trying to remove an element from an array when the onClick on the remove button is called, when the button is clicked I am getting Uncaught TypeError: Cannot read property 'name' of null

Why am I getting this error?

removeData(key) {
  console.log(key);
  const data = this.state.data;
  data[key] = null;
  this.setState({ data });
}

renderData(key){
    const user = this.props.data[key];
    console.log(user.name);
    console.log(user.id);
    return(
      <div key={key}>
          <li>  <strong> Name: </strong>  {user.name},
          <strong>  ID: </strong> {user.id} </li>
          <button onClick={() => this.props.removeData(key)}> Remove </button>
      </div>
    )
}
Share Improve this question edited Mar 9, 2018 at 17:42 Omar asked May 24, 2017 at 1:29 OmarOmar 3,4213 gold badges24 silver badges41 bronze badges 4
  • 1 what is this ?... – cpugourou Commented May 24, 2017 at 1:32
  • Right now your code is failing on your console.log('user.name);. So something is wrong with your this.props.data[key] which none of us could really be able to tell what it is. – Benjamin Commet Commented May 24, 2017 at 1:35
  • 1 implies that user is null in {user.name} – Jaromanda X Commented May 24, 2017 at 1:35
  • @cpugourou - looks like react – Jaromanda X Commented May 24, 2017 at 1:35
Add a ment  | 

3 Answers 3

Reset to default 2

Why am I getting this error?

You are explicitly setting data[key] to null:

data[key] = null;

When the ponent rerenders it presumably calls renderData with the key that was "removed" (because the property is still there, its value is just null). user will be null and accessing null.name throws an error.


Depending on what you actually want, either skip null values in your renderData method, or actually delete the entry with

delete data[key];

Assigning null does not delete a property:

var obj = {foo: 42};

// Doesn't actually remove the property
obj.foo = null;
console.log(obj);

// This removes the property
delete obj.foo;
console.log(obj);

I am trying to remove an element from an array

If you really have an array, then there more things wrong. {...this.state.data} is not an appropriate way to clone an array because you end up with an object.

To properly perform this action on an array you would do

removeData(key) {
  // Assuming `key` is the index of the element
  // Create copy
  const data = Array.from(this.state.data);
  // Remove element at index `key`
  data.splice(key, 1);
  this.setState({ data });
}

Try:

renderData(key){
    const user = this.props.data[key] || {}; // change
    console.log(user.name);
    console.log(user.id);
    return(
      <div key={key}>
          <li>  <strong> Name: </strong>  {user.name},
          <strong>  ID: </strong> {user.id} </li>
          <button onClick={() => this.props.removeData(key)}> Remove </button>
      </div>
    )

It seems like your data isn't ready when the ponent renders, so putting in a blank object will allow the ponent to render empty while the data loads.

edit: You could consider:

renderData(key){
        if (!this.props.data[key]) return null; //change
        const user = this.props.data[key];
        console.log(user.name);
        console.log(user.id);
        return(
          <div key={key}>
              <li>  <strong> Name: </strong>  {user.name},
              <strong>  ID: </strong> {user.id} </li>
              <button onClick={() => this.props.removeData(key)}> Remove </button>
          </div>
        )

This would hide the ponent as the data is being fetched. It's up to you then to municate that the data is loading to the user. You could pass down a loading prop that is set to true when the request is fired and set to false when the request returns data and show either some loading text or an animation.

Removing objects from arrays

A good way to remove objects from arrays is to use filter. Using filter keeps us safe from bugs that e from using the index inside of the map function. data.map((item,index) => <div key={index} onClick={this.removeData(index)}> {item.fruit} </div>). This can cause serious problems when removing objects from the array.

What react says about this.

We don’t remend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with ponent state. Check out Robin Pokorny’s article for an in-depth explanation on the negative impacts of using an index as a key. If you choose not to assign an explicit key to list items then React will default to using indexes as keys.

The Filter Approach

This approach takes whatever id the object has and returns every object that has a different id.

this.setState({ data: temp.filter(item => item.id !== id) });

Working Example

import React, { Component } from 'react';
import { render } from 'react-dom'; 
class App extends Component {
  constructor() {
    super();
        this.state = { 
     data:[
     { fruit: "apple", id:1 },
     { fruit: "orange", id:2 }, 
     { fruit: "pineapple", id:3 },
    ],
    }
  }
      removeData = (id) => {
      const { data } = this.state;  
      const temp = data.slice();  
      this.setState({ data: temp.filter(item => item.id !== id) });
    }
    renderData = () =>{
        const { data } = this.state;
        return data.map((item) => {
         return  <div key={item.id}>
         <label> {item.fruit} </label>
         {item.id}
         <button onClick={() => this.removeData(item.id)}> Remove </button>
         </div>         
        })     
    }
  render() {
    return (
      <div>
        {this.renderData()}
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论