在To Do App中删除函数作为React中的未定义错误返回

时间:2018-10-03 22:36:51

标签: javascript reactjs

因此,我正在开发一个待办事项列表应用程序,可以在其中向页面正文添加任务,并删除已完成的任务。我正在处理应用程序的最后一部分,使删除按钮起作用。但是我的删除按钮功能onRemove函数在未定义时返回错误。我不知道为什么要这么做,因为代码对我来说看起来不错。也许您的眼睛可以捕捉到我所缺少的东西?如果您需要参考,我还为此应用程序提供了两个其他组件。

我的App组件是处理我所有逻辑的地方,包括onRemove函数:

import React, { Component } from 'react';
import './App.css';
import Navigation from './components/Navigation';
import ListInput from './components/ListInput';
import ListName from './components/ListName';
import Item from './components/Item';
import ItemList from './components/ItemList';

class App extends Component {
  constructor() {
    super();
      this.state = {
        items: [{id: 1, text:"item 1"}, {id:2, text:"item 2"}]
      };    
  }




  addItem = (value) => {
    this.setState(state => {
      const { items } = state;
      const uuidv1 = require('uuid/v1');
      const newId = uuidv1();
      const newItem = {
        text: value, id: newId
      };


    onRemove = (id) => {
        this.setState(state => {
          const { items } = state;
          const filterdItems = 
          items.filter(items => items.id !== id);
          return { items: filterdItems };
        })
      };


      return {
        items: [ items, newItem]
      };
    }
    )
  };



  render() {
    const { items } = this.state;
    return (
      <div className="App">
       <Navigation />
       <ListName />
       <ListInput onSubmit={this.addItem} />
        <Item />
        <ItemList items={ items } 
        onRemove={ this.onRemove } />
      </div>
    );
  }
}

export default App;

这是我的商品组件

import React from 'react';

const Item = ({ text, onRemove }) =>{
    return (
        <div>
            <button 
            onClick={onRemove}>X

            </button>
            <ul>{text}</ul>
        </div>
    )}
export default Item;

这是我的ItemList组件:

import React from 'react';
import Item from './Item';

const ItemList = ({ items, onRemove }) => {
    return (
        <div>
            {items.map(items => <Item key={items.id}
            text={items.text}
            onRemove={() => onRemove(items.id)} />
            )}
        </div>
    )
}

export default ItemList;

如果您需要任何其他组件的代码或有任何其他疑问,请告诉我。预先感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

在您的App组件上,onRemove方法应该在类级别上,而不是在addItem方法内部。像这样:

addItem = (value) => {
  this.setState(state => {
    const { items } = state;
    const uuidv1 = require('uuid/v1');
    const newId = uuidv1();
    const newItem = {
      text: value, id: newId
    };

    return {
      items: [ items, newItem]
    };
  })
}

onRemove = (id) => {
  this.setState(state => {
    const { items } = state;
    const filterdItems = items.filter(item => item.id !== id);
    return { items: filterdItems };
  });
}

或者,您的onRemove方法可能会更高效,如果您知道整个数组由唯一的对象组成,则不需要遍历整个数组,可以在找到所需元素时停止对数组进行取余,然后,去掉它。像这样:

onRemove = (id) => {
  const items = [...this.state.items];
  const index = items.findIndex(item => item.id === id);

  items.splice(index, 1);

  this.setState({ items });
}

答案 1 :(得分:2)

您的onRemove方法是在您的addItem方法中定义的。这是一个很大的错字吗? :)除了这个问题,您的代码似乎可以删除。您可以在代码段中看到它。只需将您的方法移到正确的位置即可。另外,可能您的添加方法未正确处理您的状态。

return {
    items: [ items, newItem]
};

如果执行此操作,您将得到一个数组,包括您的items数组和新项目。您可能想这样做:

return {
    items: [ ...items, newItem]
};

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      items: [ { id: 1, text: "item 1" }, { id: 2, text: "item 2" } ],
    };
  }

  addItem = ( value ) => {
    this.setState( ( state ) => {
      const { items } = state;
      // const uuidv1 = require( "uuid/v1" );
      // const newId = uuidv1();
      const newItem = {
        text: value,
        // id: newId,
      };

      return {
        items: [ items, newItem ],
      };
    } );
  };

  onRemove = ( id ) => {
    this.setState( ( state ) => {
      const { items } = state;
      const filterdItems = items.filter( items => items.id !== id );
      return { items: filterdItems };
    } );
  };

  render() {
    const { items } = this.state;
    return (
      <div className="App">
        {/* <ListInput onSubmit={this.addItem} /> */}
        <Item />
        <ItemList items={items} onRemove={this.onRemove} />
      </div>
    );
  }
}

const Item = ( { text, onRemove } ) => (
  <div>
    <button onClick={onRemove}>X</button>
    <ul>{text}</ul>
  </div>
);

const ItemList = ( { items, onRemove } ) => (
  <div>
    {items.map( items => (
      <Item
        key={items.id}
        text={items.text}
        onRemove={() => onRemove( items.id )}
      />
    ) )}
  </div>
);

ReactDOM.render( <App />, document.getElementById( "root" ) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

评论后更新

...items中的三个点是spread syntax。这是散布数组或对象的非常有用的工具。在您的应用中,您想要向items数组中添加一个新项目。

[ items, newItem ];

您可以轻松地看到,如果执行此操作,将会得到以下内容:

[ [ {...}, {...} ], {yourNewItem} ]

因此,最终将得到一个数组,包括items数组和新项。因此,要解决此问题,您将使用扩展语法并扩展数组。 Sprads的意思是在这里它拾取了数组中的对象,因此您将获得没有数组的所有对象。

[ ...items, newItem ];

因此,在这里您要散布物品,然后添加一个新物品。一个新的数组将它们全部包装起来。首先是您的items的样子:

[ {..}, {..}, {yourNewITem} ]

您可以在下面的代码段中看到不同之处。

const state = {
  items: [{ id: 1, text: "item 1" }, { id: 2, text: "item 2" }]
};

const { items } = state;
const newItem = {
  text: "foo",
  id: 3,
};

const newItems = [ items, newItem ];
const fixedNewItems = [ ...items, newItem ];

console.log( newItems );
console.log( fixedNewItems );