Nano Hash - криптовалюты, майнинг, программирование

Как удалить элемент из таблицы в «React» с помощью «Redux»

По сути, приложение в этот момент отображает список «Студенты» в представлении, сохраненном в базе данных — теперь я хотел бы иметь возможность удалить студента и сохранить его. Я считаю, что ответ находится в самом компоненте.

Вот что у меня есть на данный момент — это компонент «Студенты»:

import React, { Component } from "react";
import store from "../store";
import { scrubStudent } from "../reducers";

export default class Students extends Component {
  constructor(props) {
    super(props);
    this.state = store.getState();
    this.deleteStudent = this.deleteStudent.bind(this);
  }

  deleteStudent(itemIndex) {
    console.log(this.state);
    var students = this.state.students;
    store.dispatch(scrubStudent(this.state));
    students.splice(itemIndex, 1);
    this.setState({
      students: students
    });
  }

  render() {
    var students = this.props.students;
    return (
      <div className="container">
        <div className="sixteen columns">
          <h1 className="remove-bottom">Students</h1>
          <h5>List of current students and their campus</h5>
          <hr />
        </div>
        <div className="sixteen columns">
          <div className="example">
            <div>
              <table className="u-full-width">
                <thead>
                  <tr>
                    <th>#</th>
                    <th>Name</th>
                    <th>Email</th>
                    <th>Campus</th>
                  </tr>
                </thead>
                <tbody>
                  {students.map(function(student, index) {
                    return (
                      <tr key={index}>
                        <td>
                          {student.id}
                        </td>
                        <td>
                          {student.name}
                        </td>
                        <td>
                          {student.email}
                        </td>
                        <td>
                          {student.campus}
                        </td>
                        <td>
                          <a
                            className="button button-icon"
                            onClick={this.deleteStudent(index)}
                          >
                            <i className="fa fa-remove" />
                          </a>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

Прямо сейчас я получаю index.js:90 TypeError: Cannot read property 'deleteStudent' of undefined

Заранее спасибо!

ОБНОВЛЕНИЕ

По совету Мэтью я обратился за советом (я учусь в школе) к учителю, и он помог мне связать следующее:

Но теперь я получаю следующую ошибку:

`index.js:90 TypeError: Cannot read property 'setState' of undefined`

Буду разбираться в причинах!

import React, { Component } from "react";
import store from "../store";
import { deleteStudent } from "../reducers";

export default class Students extends Component {
  constructor(props) {
    super(props);
    this.state = store.getState();
    this.deleteStudent = this.deleteStudent.bind(this);
  }

  componentDidMount() {
    this.unsubscribe = store.subscribe(function() {
      this.setState(store.getState());
    });
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  deleteStudent(index) {
    console.log(this.state);
    var students = this.state.students;
    store.dispatch(deleteStudent(index));
    this.state = store.getState();
  }

  render() {
    var students = this.props.students;
    return (
      <div className="container">
        <div className="sixteen columns">
          <h1 className="remove-bottom">Students</h1>
          <h5>List of current students and their campus</h5>
          <hr />
        </div>
        <div className="sixteen columns">
          <div className="example">
            <div>
              <table className="u-full-width">
                <thead>
                  <tr>
                    <th>#</th>
                    <th>Name</th>
                    <th>Email</th>
                    <th>Campus</th>
                  </tr>
                </thead>
                <tbody>
                  {students.map(function(student, index) {
                    return (
                      <tr key={index}>
                        <td>
                          {student.id}
                        </td>
                        <td>
                          {student.name}
                        </td>
                        <td>
                          {student.email}
                        </td>
                        <td>
                          {student.campus}
                        </td>
                        <td>
                          <a
                            className="button button-icon"
                            onClick={() => this.deleteStudent(student.id)}
                            key={index}
                          >
                            <i className="fa fa-remove" />
                          </a>
                        </td>
                      </tr>
                    );
                  }, this)}
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

Это мой редуктор:

import { combineReducers } from "redux";
import axios from "axios";

// INITIAL STATE

const initialState = {
  students: [],
  campuses: []
};

//ACTION CREATORS

const UPDATE_NAME = "UPDATE_NAME";
const ADD_STUDENT = "ADD_STUDENT";
const DELETE_STUDENT = "DELETE_STUDENT";
const GET_STUDENTS = "GET_STUDENTS";
const UPDATE_CAMPUS = "UPDATE_CAMPUS";
const GET_CAMPUS = "GET_CAMPUS";
const GET_CAMPUSES = "GET_CAMPUSES";

// ACTION CREATORS

export function updateName(name) {
  const action = {
    type: UPDATE_NAME,
    name
  };
  return action;
}

export function addStudent(student) {
  return {
    type: ADD_STUDENT,
    student
  };
}

export function scrubStudent(student) {
  return {
    type: DELETE_STUDENT,
    student
  };
}

export function getStudents(students) {
  const action = {
    type: GET_STUDENTS,
    students
  };
  return action;
}

export function updateCampus(campus) {
  const action = {
    type: UPDATE_CAMPUS,
    campus
  };
  return action;
}

export function getCampus(campus) {
  const action = {
    type: GET_CAMPUS,
    campus
  };
  return action;
}

export function getCampuses(campuses) {
  const action = {
    type: GET_CAMPUSES,
    campuses
  };
  return action;
}

//THUNK CREATORS

export function fetchStudents() {
  return function thunk(dispatch) {
    return axios
      .get("/api/students")
      .then(function(res) {
        return res.data;
      })
      .then(function(students) {
        return dispatch(getStudents(students));
      })
      .catch(function(err) {
        return console.error(err);
      });
  };
}

export function postStudent(student) {
  return function thunk(dispatch) {
    return axios
      .post("/api/students", student)
      .then(function(res) {
        return res.data;
      })
      .then(function(newStudent) {
        return dispatch(addStudent(newStudent));
      })
      .catch(function(err) {
        return console.error(err);
      });
  };
}

export function deleteStudent(student) {
  return function thunk(dispatch) {
    return axios
      .delete("/api/students/" + student.toString())
      .then(function(res) {
        return res.data;
      })
      .then(function(student) {
        return dispatch(scrubStudent(student));
      })
      .catch(function(err) {
        return console.error(err);
      });
  };
}

export function fetchCampuses() {
  return function thunk(dispatch) {
    return axios
      .get("/api/campuses")
      .then(function(res) {
        return res.data;
      })
      .then(function(campuses) {
        return dispatch(getCampuses(campuses));
      })
      .catch(function(err) {
        return console.error(err);
      });
  };
}

export function postCampus(student) {
  return function thunk(dispatch) {
    return axios
      .post("/api/campuses", campuse)
      .then(function(res) {
        return res.data;
      })
      .then(function(newCampus) {
        return dispatch(getCampus(newCampus));
      })
      .catch(function(err) {
        return console.error(err);
      });
  };
}

// REDUCER

const rootReducer = function(state = initialState, action) {
  var newState = Object.assign({}, state);

  switch (action.type) {
    case GET_STUDENTS:
      newState.students = state.students.concat(action.students);
      return newState;

    case ADD_STUDENT:
      newState.students = state.students.concat([action.student]);
      return newState;

    case DELETE_STUDENT:
      newState.students = state.students.concat([action.student]);
      return newState;

    case GET_CAMPUSES:
      newState.campuses = state.campuses.concat(action.campuses);
      return newState;

    case GET_CAMPUS:
      newState.campuses = state.campuses.concat([action.campus]);
      return newState;

    default:
      return state;
  }
};

export default rootReducer;
01.09.2017

  • Ответ ниже прямо объясняет, почему вы получаете сообщение об ошибке, но, читая свой код, вы упускаете один из фундаментальных моментов Redux... **разделение проблем** см. мой ответ здесь для получения некоторой связанной информации stackoverflow. com/questions/45936949/ 01.09.2017
  • @MatthewBrent В самом деле, когда я тестировал этот план действий, я достиг максимального стека вызовов, где все было не так! Спасибо за ссылку. 01.09.2017
  • @AntonioPavicevac-Ortiz, ты проверил мой ответ? У вас все еще есть проблема? 01.09.2017
  • @Dekel Эй, да, я сделал! Спасибо. У меня есть некоторые другие проблемы, как вы можете видеть, основываясь на том, что указал Мэтью. Я обновил свой вопрос, чтобы отразить прогресс до сих пор! 01.09.2017
  • Не зная, какая строка является строкой 90 в приведенном выше коде, трудно помочь, но я снова предполагаю, что это проблема области. Когда вы используете function() {...}, вы теряете область своего текущего this, поэтому в своем ответе я сказал, что вы должны использовать функцию стрелки. 01.09.2017
  • Интересно. Я полностью понимаю, основываясь на том, что вы указали ранее, почему это было проблемой. Но в консоли теперь я получаю эту ошибку в отношении this.setState(store.getState()) — разве this не является самим компонентом в componentDidMount? Я также добавил свой редуктор, который представляет собой index.js. 01.09.2017
  • В то время как происходили некоторые другие вещи, по сути, половина проблемы заключалась в этой привязке. В моем недавнем обновлении у меня была такая же проблема! Изменение его на componentDidMount() { this.unsubscribe = store.subscribe(() => { this.setState(store.getState()); }); } решило это! СПАСИБО @Dekel 01.09.2017

Ответы:


1

Вы должны использовать функцию стрелки, чтобы сохранить соответствующий контекст в функции карты:

{students.map((student, index) => {

Таким образом, когда вы используете this внутри функции - это ваш текущий компонент.

01.09.2017
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..