从表中删除行(无法读取 null 的属性'data')



我是Gatsbyjs和reactjs的新手,我仍然不太了解props.and状态是如何工作的。

我正在构建这个简单的应用程序,该应用程序从 API 获取客户列表以及每个客户的任务列表。

我正在使用Reach/Router来渲染组件。一切都按预期工作,就像显示一个带有客户列表的表格一样,当我单击客户时,会呈现一个新页面,其中显示了该客户的任务列表。

现在,我正在尝试使表格可编辑。我首先尝试简单地删除一些行。这就是我卡住的地方。

编辑

我相信我得到了Uncaught TypeError: Cannot read property 'data' of null的错误,因为我正在尝试访问由fetch.js类管理的数据(状态(。如何将数据(状态(传递给 ClientTasks 类?

---

我有以下代码

索引.js

import React from "react"
import { createHistory, LocationProvider } from '@reach/router'
import createHashSource from '../utils/hash-source'
import { ToastContainer } from 'react-toastify';
import "../css/main.css"
import "../css/materialize.css"
import "../css/blackjack.css"
import '../../node_modules/react-toastify/dist/ReactToastify.css';

import { NavBar } from '../components/navBar'
import { Main } from '../components/main'
const isClient = typeof window !== 'undefined' && window;
let source 
let history 
if (typeof window !== `undefined` ) {
source = createHashSource()
history = createHistory(source)
}
class App extends React.Component { 
render() {
return (
<LocationProvider history={history}>
<div className="app" >
<NavBar/>
<Main/>
<ToastContainer position="bottom-right"/>
</div>
</LocationProvider>
)
}
}
export default App

主.js

import React from 'react'
import { Router } from "@reach/router"
import { Home } from '../components/home'
import { Customers } from './customers';
import { ClientTasks } from './clientTasks1';

const Main = () => (
<main className="main container">
<Router className="row">
<Home path='/'/>
<Customers path='customers'/>
<ClientTasks path="customers/tasks/:customerId"/>
</Router>
</main>
)
export { Main }

获取.js

我使用此文件作为单个类组件工作,帮助我获取正在显示的表(客户和任务(的数据。它按原样工作正常。可能有更好的方法可以做到这一点,但现在这就是我的做法。欢迎任何指示。

import React, { Component } from 'react'
const axios = require('axios')
class Fetch extends React.Component {
constructor(props) {
super(props);
this.state = {
data: null,
isLoading: true,
error: null,
};
}
componentDidMount() {
this.setState({ isLoading: true });
axios.get(this.props.url)
.then(result => this.setState({
data: result.data,
isLoading: false
}))
.catch(error => this.setState({
error,
isLoading: false
}));
}
render() {
return this.props.children(this.state);
}
}

export default Fetch

客户.js

这是我展示客户表的地方。我在每个客户上都有链接,并在"到达/路由器"的帮助下呈现客户任务表。

import React, { Component } from 'react'
import { Link } from "@reach/router"
import Fetch from './fetch'
import { UploadForm } from './upLoadtoS3'
import { AnimatedDiv } from './AnimatedDiv'
const APIURL = `https://SomeAIPURL`
let APIQuery = `customers`
const Customers = () => (
<Fetch url={APIURL + APIQuery}>
{({ data, isLoading, error }) => {
if (!data) {
return (
<div className="progress">
<div className="indeterminate"></div>
</div>)
}
if (error) {
return <p>{error.message}</p>;
}
if (isLoading) {
return (
<div className="progress">
<div className="indeterminate"></div>
</div>)
}
return (
<AnimatedDiv className='col m12 s12'>
<h1> Client List </h1>
<table className='highlight'>
<thead>
<tr>
<th>#</th>
<th>Client ID</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{data.map((customer, i) => (
<tr key={customer.customerid}>
<td>{i + 1}</td>
<td>
<Link to={`tasks/${customer.customerid}`}>{customer.customerid}</Link>
</td>
<td>{customer.enabled}</td>
</tr>
))}
</tbody>
</table>
<UploadForm></UploadForm>
</AnimatedDiv>
);
}
}
</Fetch>
)
export { Customers }

客户端任务.js

再次调用 Fetch,并使用从 API 提取的数据填充表。 我使用另一个文件来定义此表的内容。listTasks.js

import React, { Component } from 'react'
import { Link } from "@reach/router"
import Fetch from './fetch'
// import Delete from './delete'
import { AnimatedDiv } from './AnimatedDiv'
import DisplayList from './listTasks'
const APIURL = `https://SomeAIPURL`
const CUSTOMERQUERY = `tasks?customerid=`
const TASKQUERY = `&taskid=`

class ClientTasks extends React.Component {
handleDelete(taskToBeDeleted) {
// console.log(taskToBeDeleted);
let newData = this.state.data.filter((_data) => {
return _data != taskToBeDeleted
});
this.setState({ data: newData })
}
render() {
let customerId = this.props.customerId
return (
<Fetch url={APIURL + CUSTOMERQUERY + customerId}>
{({ data, isLoading, error }) => {
if (!data) {
return (
<div className="progress">
<div className="indeterminate"></div>
</div>)
}
if (error) {
return <p>{error.message}</p>;
}
if (isLoading) {
return (
<div className="progress">
<div className="indeterminate"></div>
</div>)
}
else {
return (
<AnimatedDiv className='col m12 s12'>
<h1>{customerId} Tasks</h1>
<table id="customerList" className="highlight" >
<thead>
<tr>
<th>Task ID</th>
<th>Qty</th>
<th>Asset Category</th>
<th>Asset</th>
<th>Location</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<DisplayList handleDelete={this.handleDelete.bind(this)} data={data}/>
</table>
<Link to='/customers'> Back to Client List ... </Link>
</AnimatedDiv>
)
}
}
}
</Fetch>
)
}
}
export { ClientTasks }

>

在这里,我有一个onClick函数,可以在ClientTasks.js文件中运行handleDelete

如果我console.log(taskstobedeleted),则控制台会向我显示我正在尝试删除的行的内容。 这是我得到的。 然后我尝试在clientasks.js中使用以下函数,但我在控制台中出现错误,说Cannot read property 'data' of null),我相信这是因为数据的道具是可访问的,这个clientTasks类。

我仍在学习,并且有更好的方法来构建代码,但是我已经碰壁了,我不想从头开始重建应用程序,如果我这样做,我可能会使用redux,但这是以后的另一个教训。我认为我的这个项目足够小,还不需要 Redux。

可以以某种方式给我任何有关如何删除表行的指示吗?

handleDelete(taskToBeDeleted) {
// console.log(taskToBeDeleted);
let newData = this.state.data.filter((_data) => {
return _data != taskToBeDeleted
});
this.setState({ data: newData })
}

列表任务.js

import React from 'react'
import { Icon } from 'react-icons-kit'
import { ic_delete_forever } from 'react-icons-kit/md/ic_delete_forever'
export default class DisplayList extends React.Component {
render() {
return (
<tbody>
{this.props.data.map((task) => (
<tr key={task.taskid}>
<td>{task.taskid}</td>
<td>{task.qty}</td>
<td>{task.category}</td>
<td>{task.asset}</td>
<td>{task.location}</td>
<td>{task.enabled}</td>
<td>
<button style={{ padding: '0px', background: 'transparent', border: '0', cursor: 'pointer' }} onClick={this.props.handleDelete.bind(this, task)} >
<Icon style={{ color: 'red' }} icon={ic_delete_forever} />
</button>
</td>
</tr>
))}
</tbody>
)
}
}

我认为你的函数应该是这样的:

handleDelete(taskToBeDeleted) {
// console.log(taskToBeDeleted);
let newData = this.state.data.filter((_data) => _data.taskid != taskToBeDeleted.taskid});
this.setState({ data: newData })
}

如果您的控制台为您提供了所需的对象,那么首先,您不需要返回箭头函数,因为返回是隐式的。其次,所有任务都已返回,因为您要求两个对象是否相同,即使它们内部具有相同的键值对,它们也始终为 false。它们有不同的参考。这就是为什么我使用 id 的原因,因为我认为该键的值是数字,您可以使用运算符 == 或 != 来评估它

最新更新