Удалить строку из таблицы (невозможно прочитать свойство 'data' из null) - PullRequest
0 голосов
/ 08 сентября 2018

Я новичок в Gatsbyjs и реагировать, и я до сих пор не понимаю, как работают реквизиты и состояния.

Я создаю это простое приложение, которое получает список клиентов из API и список задач для каждого клиента.

Я использую Reach / Router для рендеринга компонентов. Все работает, как и ожидалось, для отображения таблицы со списком клиентов, и когда я нажимаю на клиента, отображается новая страница, которая показывает список задач для этого указанного клиента.

Теперь я пытаюсь сделать таблицу редактируемой. Я начинаю с попытки просто удалить несколько строк. это где я застрял.

редактировать

Я считаю, что я получаю ошибку Uncaught TypeError: Cannot read property 'data' of null, потому что я пытаюсь получить доступ к данным (состоянию), которыми управляет класс fetch.js. Как передать данные (состояние) в класс ClientTasks?

---

У меня есть следующий код

index.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

main.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 }

fetch.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

Customers.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 }

ClientTasks.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 функция, которая запускает handleDelete внутри файла ClientTasks.js.

Если я console.log(taskstobedeleted), то консоль показывает мне содержимое строки, которую я пытаюсь удалить. Это так же, как я получаю. Затем я пытаюсь использовать следующую функцию в clientasks.js, но я получаю сообщение об ошибке в консоли, которое говорит Cannot read property 'data' of null), и я считаю, что это потому, что реквизиты данных доступны, что этот класс clientTasks.

Я все еще учусь, и есть лучшие способы структурировать код, но я попал в стену и не хочу перестраивать приложение с нуля, если бы я это сделал, я бы, вероятно, использовал избыточность, но это еще один урок Для последующего. Я подумал, что этот мой проект достаточно мал и пока не нуждается в Redux.

Может ли я как-нибудь подсказать, как удалить строки из моей таблицы?

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

Listtasks.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>
        )
    }

}

1 Ответ

0 голосов
/ 08 сентября 2018

Я думаю, что ваша функция должна быть такой:

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

Если ваша консоль предоставляет вам объект, который вы хотели, то, во-первых, вам не нужно возвращать в функции стрелки, поскольку return неявен. Во-вторых, все ваши задачи были возвращены, потому что вы запрашивали два объекта, они одинаковы, что всегда будет ложным, даже если внутри них есть одинаковые пары ключ-значение. У них разные ссылки. Вот почему я использовал id, так как полагаю, что значение этого ключа - число, и вы можете оценить это с помощью оператора == или! =

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...