У меня есть простое приложение - менеджер контактов с функцией 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
и что я должен изменить в форме, которая создает рабочий контейнер для обновления контакта?
Я буду очень признателен за любую помощь или любые советы.
Заранее спасибо.