Функция сортировки React / Redux не обновляет состояние - PullRequest
1 голос
/ 19 марта 2019

У меня есть простое приложение React / Redux, которое отображает список автомобилей на основе моего Rails API.

Я пытаюсь добавить функцию сортировки, которая алфавитирует автомобили по названию.

Хотя моя переменная orgArray фактически находится в алфавитном порядке, когда я его консолью. Log, мой инструмент разработчика Redux сообщает states are equal после нажатия кнопки сортировки - поэтому мой пользовательский интерфейс не обновляется.

Вот мой код:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import CarCard from '../components/CarCard';
import CarForm from './CarForm';
import './Cars.css';
import { getCars } from '../actions/cars';
import { sortCar } from '../actions/cars';

Component.defaultProps = {
  cars: { cars: [] }
}

class Cars extends Component {
  constructor(props) {
    super(props)
      this.state = {
        cars: [],
        sortedCars: []
      };
  }

sortAlphabetically = () => {
    console.log("sort button clicked")
    const newArray = [].concat(this.props.cars.cars)
    const orgArray = newArray.sort(function (a,b) {
      var nameA = a.name.toUpperCase();
      var nameB = b.name.toUpperCase();
          if (nameA < nameB) {
            return -1;
          } else if (nameA > nameB) {
            return 1;
          } 
            return 0;
          }, () => this.setState({ cars: orgArray }))  
            console.log(orgArray)
            this.props.sortCar(orgArray);
          }

    componentDidMount() {
        this.props.getCars()
        this.setState({cars: this.props.cars})
        }


    render() {
        return (
        <div className="CarsContainer">
    <h3>Cars Container</h3> 
        <button onClick={this.sortAlphabetically}>Sort</button>
        {this.props.cars.cars && this.props.cars.cars.map(car => <CarCard key={car.id} car={car} />)}  
        {/* {this.state.cars.cars && this.state.cars.cars.map(car => <CarCard key={car.id} car={car} />)}           */}
        <CarForm />
    </div>
    );
  }
}

 const mapStateToProps = (state) => {
   return ({
    cars: state.cars
  })
}

const mapDispatchToProps = (dispatch) => {
  return {
    sortCar: (cars) => dispatch(sortCar(cars)),
    getCars: (cars) => dispatch(getCars(cars))
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Cars);

Я бы предположил, что mapStateToProps или добавление sortedCars: [] в мой начальный setState сработало бы.

По сути, мои реквизиты обновляются, но мне нужно также обновить свое состояние - хотя я не уверен, что мне не хватает.

ОБНОВЛЕНИЕ:

Вот мой создатель действий и асинхронное действие, если оно помогает:

const sortCars = cars => {
 return {
    type: 'SORT_CARS',
    cars
  }
}

// Async Actions

export const sortCar = (cars) => {
  console.log(cars, 'cars object');
  return dispatch => {
    dispatch(sortCars(cars))
   }
}

UPDATE:

Вот и Редуктор:

export default (state = {cars: []}, action) => {
switch(action.type) {
    case 'GET_CARS_SUCCESS':

    return Object.assign({}, state, {cars: action.payload})

    case 'CREATE_CAR_SUCCESS':

    return Object.assign({}, state, {cars: action.payload})

    case 'REMOVE_CAR;':
    return state.filter(car => car.id !== action.id)

    case 'SORT_CARS;':
    return Object.assign({}, state, { cars: action.payload})

    default:
        return state;
  }
}

Ответы [ 3 ]

1 голос
/ 19 марта 2019

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

Кроме того, я думаю, что проблема в том, что вы передаете orgArray this.props.sortCar(orgArray), который является массивом вместо объекта с ключом "cars" и значениями внутри.

Кроме того, вызов setState объявляется как анонимная функция, а не фактически выполняется после сортировки.

Убедитесь, что у вас есть отступ.

0 голосов
/ 19 марта 2019

Получил решение, которое использует локальное состояние вместо хранилища Redux (не идеально, но выполняет эту функцию).

Добавление async к моему componentDidMount вместе с await ожидает обновления данных, пока локальное состояние не изменится, что затем отражается в моем пользовательском интерфейсе.

Спасибо всем за помощь.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import CarCard from '../components/CarCard';
import CarForm from './CarForm';
import './Cars.css';
import { getCars } from '../actions/cars';
import { sortCar } from '../actions/cars';

Component.defaultProps = {
  cars: { cars: [] }
}

class Cars extends Component {
  constructor(props) {
  super(props)
  this.state = {
    cars: [],
    sortedCars: []
  };
}

sortAlphabetically = () => {
    console.log("sort button clicked")
    const newArray = [].concat(this.props.cars.cars)
    const orgArray = newArray.sort(function (a,b) {
          var nameA = a.name.toUpperCase();
          var nameB = b.name.toUpperCase();
              if (nameA < nameB) {
                return -1;
              } else if (nameA > nameB) {
                return 1;
              } 
               return 0;
              })  
            console.log(orgArray)
            this.props.sortCar(orgArray);
            this.setState({ cars: {cars: orgArray} })
}

async componentDidMount() {
    await this.props.getCars()
    this.setState({cars: this.props.cars})
}

render() {
    return (
    <div className="CarsContainer">
        <h3>Cars Container</h3> 
        <button onClick={this.sortAlphabetically}>Sort</button>
        {this.state.cars.cars && this.state.cars.cars.map(car => <CarCard key={car.id} car={car} />)}          
        <CarForm />
    </div>
    );
  }
}

 const mapStateToProps = (state) => {
  return ({
    cars: state.cars
  })
}

const mapDispatchToProps = (dispatch) => {
  return {
    sortCar: (cars) => dispatch(sortCar(cars)),
    getCars: (cars) => dispatch(getCars(cars))
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Cars);
0 голосов
/ 19 марта 2019

У сортировки есть только один аргумент (функция сортировки). И в вашем sortAlphabetically метод setState (помещенный как второй аргумент sort) не вызывается. Метод должен быть примерно таким (я его не проверял)

sortAlphabetically = () => {
    console.log("sort button clicked")
    const newArray = this.props.cars.cars.slice();
    const orgArray = newArray.sort(function (a, b) {
        var nameA = a.name.toUpperCase();
        var nameB = b.name.toUpperCase();
        if (nameA < nameB) {
            return -1;
        } else if (nameA > nameB) {
            return 1;
        }
        return 0;
    });
    this.setState({ cars: orgArray }, () => {
        console.log(orgArray);
        this.props.sortCar(orgArray);
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...