Как обновить глобальное состояние с помощью приставки и удалить элемент из глобального состояния - PullRequest
1 голос
/ 09 марта 2020

Я пытаюсь выучить избыточность, но я застрял в этой концепции о том, как правильно использовать deleteCar, который у меня есть в действиях. Редуктор работает хорошо, но проблема в глобальном состоянии cars, как я могу обновить состояние автомобилей в компоненте Car, а затем вызвать функцию deleteCar и изменить состояние cars. Когда я печатаю состояние автомобилей в компоненте Car, оно пустое.

У меня есть компонент, который называется Автомобили, который является родительским компонентом Car (один автомобиль)

import React from "react";
import Car from "../Car";
import { connect } from "react-redux";

class Cars extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      cars: []
    };
  }
  componentDidMount() {
    fetch(url)
      .then(response => response.json())
      .then(data => this.setState({ cars: data }));
  }
  render() {
    const { cars } = this.state;
    return (
      <div>
        {cars.map(c => (
          <Car key={c.id} make={c.make} price={c.price} id={c.id} />
        ))}
      </div>
    );
  }
}

const mapStateToProps = reduxStoreState => {
  return {
    cars: reduxStoreState.cars
  };
};

export default connect(mapStateToProps)(Cars);

Single car

import React from "react";
import { deleteCar } from "../../actions/delete";
import { connect } from "react-redux";

const Car = ({ deleteCar, make, price, id }) => {
  return (
    <div className="card m-4">
      <div className="row">
        <div className="col">
          <h3>{make}</h3>
          <p>{price}</p>
        </div>
      </div>
      <div className="row">
        <button
          className="btn btn-danger"
          onClick={() =>
            deleteCar({
              id: id,
              make: make,
              price: price
            })
          }
        >
          Delete Car
        </button>
      </div>
    </div>
  );
};
const mapStateToProps = reduxStoreState => {
  return {
    cars: reduxStoreState.cars
  };
};

export default connect(mapStateToProps, { deleteCar })(Car);

Действие

import { DELETE } from "../constants";
export const deleteCar = (payload) => {
  return {
    type: DELETE,
    payload: payload
  };
};

Редуктор

import { ADD, DELETE, EDIT } from "../constants";

export default function(state = { cars: [] }, action) {
  switch (action.type) {
    case ADD:
      return {
        ...state,
        cars: [...state.cars, action.payload]
      };
    case DELETE:
      return {
        ...state,
        cars: state.cars.filter(obj => obj !== action.payload)
      };
    case EDIT:
      return {
        ...state,
        cars: action.payload
      };
    default:
      return state;
  }
}

1 Ответ

2 голосов
/ 09 марта 2020

Приведенный ниже код не будет работать должным образом:

cars: state.cars.filter(obj => obj !== action.payload)

В JavaScript объекты хранятся в переменных в качестве ссылок. Вызывая действие удаления следующим образом:

deleteCar({
  id: id,
  make: make,
  price: price
})

Каждый раз вы создаете новый объект, чтобы он никогда не совпадал и он не был отфильтрован.

Это появляется как если бы сравнение было бы таким:

{ id: id, make: make, price: price } === { id: id, make: make, price: price }

Но в действительности это сравнивается более примерно так:

// Both objects contain the same values
// But will not evaluate as equal because the references are different
'object_reference_1' === 'object_reference_2'

Вместо этого я бы рекомендовал проверить по id например:

cars: state.cars.filter(obj => obj.id !== action.payload.id)

Вторая проблема заключается в том, что вы дублировали локальное и избыточное состояние в Cars.

Вместо использования локального состояния, отправьте действие для заполнения избыточного числа. Это может выглядеть примерно так:

componentDidMount() {
  fetch(url)
  .then(response => response.json())
  // Or preferably create a new action and call it like you did `deleteCar`
  .then(data => this.props.dispatch({ type: 'INITIALIZE', cars: data }));
}

Затем в редукторе добавьте этот случай:

switch (action.type) {
  case 'INITIALIZE':
    return {
      ...state,
      cars: action.payload
    };

Убедитесь, что вы удалили локальное состояние для cars и заменили const { cars } = this.state; на используйте this.props.

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