Реализация действий по удалению и обновлению с помощью response-redux, маршрутов, redux-обещания и с rails api - PullRequest
0 голосов
/ 11 июня 2019

У меня есть простое приложение - менеджер контактов с функцией CRUD. Я уже создал:

  • list, new и show реактивные контейнеры,
  • actions и reducers для них Но не может правильно реализовать действия и редукторы для обновите, удалите и создайте контейнер обновлений.

Например, мой код для действий - deleteContact и updateContact выглядит так:

# for update action
export function updateContact(id, body, callback) {

   const request = fetch(`${ROOT_URL}/contacts/${id}`, {
      method: "PATCH",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(body)
    })
      .then(response => response.json())
      .then(callback)
      .catch(error => console.log(error))
    return {
      type: CONTACT_UPDATED,
      payload: request
    };
}

# for delete action
export function deleteContact(id, body, callback) {
    const request = fetch(`${ROOT_URL}/contacts/${id}`, {
      method: "DELETE",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(body)
    }).then(response => response.json())
      .then(callback);
    return {
      type: CONTACT_DELETED,
      payload: request
    };
  }

но в браузере в консоли я получил следующее: payload: SyntaxError: Unexpected token < in JSON at position 0, error: true

и во вкладке сети: ActiveRecord::RecordNotFound in Api::V1::ContactsController#destroy Couldn't find Contact with 'id'=[object Object]

Кажется, я не передаю необходимый идентификатор, который хочу удалить. Что я делаю неправильно?

Должен ли я предоставить 3 параметра для этой функции: идентификатор, тело, обратный вызов или просто идентификатор?

Обратный вызов, который я использую для перенаправления после действия, например, когда вы создали действие, вы будете перенаправлены в контейнер списка контактов.

Похоже, из contact_new контейнера:

onSubmit = (values) => {
    this.props.createContact(values, (contact) => {
      this.props.history.push('/');
      return contact;
    });
  }

Я не понимаю, почему появляется ошибка с Unexpected token < in JSON at position 0?

Означает ли это, что я неправильно анализирую мой API, когда делаю запрос на удаление? Какой лучший способ это исправить?

мой код для contact_reducers:

import { FETCH_CONTACTS, FETCH_CONTACT, CONTACT_CREATED, CONTACT_UPDATED, CONTACT_DELETED } from '../actions';

export default function postsReducer(state = [], action) {
  const { payload, type } = action;
  switch (type) {
    case FETCH_CONTACTS:
      return payload;
    case FETCH_CONTACT:
      const contacts = state.splice(0);
      const index = contacts.findIndex((contact) => contact.id === payload.id);
      if (index === -1) {
        contacts.push(payload);
      } else {
        contacts.splice(index, 1, payload);
      }
      return contacts;
    case CONTACT_CREATED:
      return [...state, payload];

    case CONTACT_UPDATED:
      // return [...state, payload];
      const i = state.findIndex(contact => contact.id === payload.id);
      return [
        ...state.slice(0, i),
        payload,
        ...state.slice(i + 1)
      ]
    case CONTACT_DELETED:
      return state.filter(contact => contact.id === payload.id);
    default:
      return state;
  }
}

редукторы для fetching contacts, specific contact, а также для create contact работают.

Но для updating и deleting контактов нет.

Пожалуйста, дайте мне совет о том, как должны выглядеть действия и редукторы для удаления и обновления?

мой код для contacts_show контейнера:

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { fetchContact, deleteContact } from '../actions/index';

class ContactsShow extends Component {
  constructor(props)
  {
    super(props);
    this.deleteContact = this.deleteContact.bind(this);
  }

  // onSubmit = (values) => {
  //   this.props.deleteContact(values, (contact) => {
  //     this.props.history.push('/');
  //     return contact;
  //   });
  // }

  deleteContact(id, values) {
    this.props.deleteContact(id, values);
  }

  componentDidMount() {
    if (!this.props.contact) {
      this.props.fetchContact(this.props.match.params.id);
    }
  }

  render() {
    const { contact } = this.props;

    if (!contact) {
      return <p>Loading...</p>;
    }

    return (
      <div>
        <div className="contact-item">
          <h3>{contact.first_name} {contact.last_name}</h3>
          <p> Email: {contact.email}</p>
          <p> Phone number: {contact.phone_number}</p>
        </div>
        <button className="btn btn-primary" type="submit" disabled={this.props.pristine || this.props.submitting}>
            Update Contact
        </button>
        <button className="btn btn-danger" type="button" onClick={this.deleteContact}>
            Delete
        </button>
        <Link to="/">
          Back
        </Link>
      </div>
    );
  }
}

function mapStateToProps(state, ownProps) {
  return {
    contact: state.contacts.find((contact) => {
      return contact.id === parseInt(ownProps.match.params.id)
    })
  };
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ fetchContact, deleteContact }, dispatch);
}

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

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

Пожалуйста, дайте мне подсказку. Я действительно застрял.

my contact_new выглядит так:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { reduxForm, Field } from 'redux-form';
import { createContact } from '../actions';

class ContactsNew extends Component {
  onSubmit = (values) => {
    this.props.createContact(values, (contact) => {
      this.props.history.push('/');
      return contact;
    });
  }

  renderField(field) {
    return (
      <div className="form-group">
        <label>{field.label}</label>
        <input
          className="form-control"
          type={field.type}
          {...field.input}
        />
      </div>
    );
  }

  render() {
    return (
      <div>
        <form onSubmit={this.props.handleSubmit(this.onSubmit)}>
          <Field
            label="First name"
            name="first_name"
            type="text"
            component={this.renderField}
          />

          <Field
            label="Last name"
            name="last_name"
            type="text"
            component={this.renderField}
          />

          <Field
            label="Email"
            name="email"
            type="text"
            component={this.renderField}
          />

          <Field
            label="Phone number"
            name="phone_number"
            type="text"
            component={this.renderField}
          />

          <button className="btn btn-primary" type="submit" disabled={this.props.pristine || this.props.submitting}>
            Create Contact
          </button>
        </form>
      </div>
    );
  }
}


export default reduxForm({
  form: 'newContactForm' // a unique identifier
})(
  connect(null, { createContact })(ContactsNew)
);

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

Я буду очень признателен за любую помощь или любые советы. Заранее спасибо.

...