Получить объект по идентификатору, используя идентификатор другого объекта в React Component - PullRequest
0 голосов
/ 24 апреля 2020

Я пытаюсь создать веб-приложение, используя React, Redux и Django REST framework. API предоставляет два разных типа пользователей. Одной из них является модель с именем Counselor, владельцем которой является auth.User, как показано в коде ниже:

class Counselor(models.Model):
    owner = models.ForeignKey('auth.User',
                              related_name='counselors',
                              on_delete=models.CASCADE)
    # other fields...

Класс Counselor будет хранить идентификатор владельца, а API предоставляет конечную точку для получить владельца по его идентификатору, то есть r'^users/(?P<pk>[0-9]+)/$' и другой конечной точке, чтобы получить все объекты Counselor в коллекции.

Используя react-redux, я создал компонент, который будет вызывать действие для получения всех Counselor объекты и еще один объект для извлечения владельца по идентификатору владельца (консультанта).

Я хотел бы отобразить только Counselor 'first_name и last_name в форме компонента , Однако действие возвращает undefined.

Ниже кода и то, что я пытался сделать:

пользовательский редуктор

import {
  // ...
  GET_USER,
} from "../actions/types";

const initialState = {
  token: localStorage.getItem("token"),
  isAuthenticated: false,
  isLoading: false,
  user: null,
};

export default function (state = initialState, action) {
  switch (action.type) {
    // ...
    case USER_LOADED:
    case GET_USER:
      return {
        ...state,
        isAuthenticated: true,
        isLoading: false,
        user: action.payload,
      };
    // ...
    default:
      return state;
  }
}

действие пользователя

// GET User
export const getUser = (id) => (dispatch, getState) => {
  axios
    .get(`/api/users/${id}/`, tokenConfig(getState))
    .then((res) => {
      dispatch({
        type: GET_USER,
        payload: res.data,
      });
    })
    .catch((err) => {
      dispatch(returnErrors(err.response.data, err.response.status));
    });
};

редуктор консультанта

import {
  GET_COUNSELOR,
  // ...
} from "../actions/types";

const initialState = {
  isRegistering: false,
  counselors: [],
};

export default function (state = initialState, action) {
  switch (action.type) {
    // ...
    case GET_COUNSELOR:
      return {
        ...state,
        isRegistering: false,
        counselors: action.payload,
      };
    // ...
    default:
      return state;
  }
}

действие консультанта

// GET Counselor
export const getCounselors = () => (dispatch, getState) => {
  axios
    .get("/api/counselors/", tokenConfig(getState))
    .then((res) => {
      dispatch({
        type: GET_COUNSELOR,
        payload: res.data,
      });
    })
    .catch((err) =>
      dispatch(returnErrors(err.response.data, err.response.status))
    );
};

В компоненте React я буду называть оба действия getCounselors и getUser. Когда вызывается getCounselors, заполняется состояние counselors, поэтому я могу получить идентификатор. Однако, когда вызывается getUser(counselor.id), объект имеет вид undefined.

Код компонента ниже:

Компонент формы (точка, где я вызвал getUser, помеченный комментарием)

import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";

import { getCounselors } from "../../actions/counselors";
import { getUser } from "../../actions/auth";
import { postAppointment } from "../../actions/appointments";

export class Form extends Component {
  state = {
    title: "",
    date: "",
    start_time: "",
    end_time: "",
    location: "",
    description: "",
    counselor: "",
  };

  static propTypes = {
    counselors: PropTypes.array.isRequired,
    postAppointment: PropTypes.func.isRequired,
    getUser: PropTypes.func.isRequired,
  };

  componentDidMount() {
    this.props.getCounselors();
  }

  onChange = (e) => this.setState({ [e.target.name]: e.target.value });

  onSubmit = (e) => {
    e.preventDefault();

    const {
      title,
      date,
      start_time,
      end_time,
      location,
      description,
      counselor,
    } = this.state;

    const appointment = {
      title,
      date,
      start_time,
      end_time,
      location,
      description,
      counselor,
    };
    this.props.postAppointment(appointment);
    this.setState({
      title: "",
      date: "",
      start_time: "",
      end_time: "",
      location: "",
      description: "",
      counselor: "",
    });
  };

  render() {
    const {
      title,
      date,
      start_time,
      end_time,
      location,
      description,
      counselor,
    } = this.state;

    return (
      <div className="col-md-6 m-auto">
        <div className="card card-body mt-4 mb-4">
          <h2>Book an Appointment</h2>
          <form onSubmit={this.onSubmit}>
            {/* some divs ... */}
            <div className="form-group">
              <label>Counselor</label>
              <select
                type="text"
                className="form-control"
                name="counselor"
                onChange={this.onChange}
                value={counselor}
              >
                <option value="" disabled>
                  Choose...
                </option>
                {this.props.counselors.map((counselor) => (
                  <option key={counselor.id}>
                    {this.props.getUser(counselor.owner)} {/* HERE!!! */}
                  </option>
                ))}
              </select>
            </div>
            <div className="form-group">
              <button type="submit" className="btn btn-primary">
                Book
              </button>
            </div>
          </form>
        </div>
      </div>
    );
  }
}

const mapStateToProps = (state) => ({
  counselors: state.counselors.counselors,
});

export default connect(mapStateToProps, {
  getCounselors,
  postAppointment,
  getUser,
})(Form);

Не могли бы вы посоветовать? Спасибо!

1 Ответ

0 голосов
/ 24 апреля 2020

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

  1. сделать конечную точку API для получения массива пользователей вместо того, чтобы делать много запросов к серверу
  2. сделать этот запрос в componentDidUpdate

На самом деле я не знаю архитектуру вашего приложения, но выглядит немного странно, что вы получаете массив консультантов с сервера, затем получаете идентификатор для каждого объекта и снова делаете запрос, но, возможно, он вам действительно нужен (в любом случае обратите внимание на это)

...