Reputation: 5987
I am using react/redux and the error is happening after a deleteRequest is called using an action. The reducer removes the item from the array and I think that is why this is happening, but I should be changing the location so it should not be rendering this page anymore.
The direct error is coming from the Post component down below from the this.props.deleteRecord
in the catch block.
I am also using turbo which is how I make the deleteRequest and store the data. If you need a reference here is the docs. https://www.turbo360.co/docs
Reducer:
import constants from '../constants';
const initialState = {
all: null
};
export default (state = initialState, action) => {
switch (action.type) {
case constants.POST_CREATED:
return {
...state,
all: state.all.concat(action.data),
[action.data.id]: action.data
};
case constants.RECORD_UPDATED:
return {
...state,
[action.data.id]: action.data,
all: all.map(item => (item.id === action.data.id ? action.data : item))
};
case constants.RECORD_DELETED:
const newState = {
...state,
all: state.all.filter(item => item.id !== action.data.id)
};
delete newState[action.payload.id];
return newState;
case constants.FETCH_POSTS:
const sortedData = action.data.sort((a, b) => {
return new Date(b.timestamp) - new Date(a.timestamp);
});
return { ...state, all: sortedData };
case constants.FETCH_POST:
return { ...state, [action.data.id]: action.data };
default:
return state;
}
};
Component:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import swal from 'sweetalert2/dist/sweetalert2.all.min.js';
import actions from '../../actions';
import { DateUtils } from '../../utils';
import { Reply } from '../containers';
import { UpdateRecord } from '../view';
class Post extends Component {
constructor() {
super();
this.state = {
editShow: false
};
}
componentDidMount() {
const { id } = this.props.match.params;
if (this.props.posts[id] != null) {
return;
}
this.props
.getRecord(id)
.then(() => {})
.catch(err => {
console.log(err);
});
}
updateRecord(params) {
const { id } = this.props.match.params;
const post = this.props.posts[id];
const { currentUser } = this.props.user;
if (post.profile.id !== currentUser.id) {
swal({
title: 'Oops...',
text: 'Must be owner of post',
type: 'error'
});
return;
}
this.props
.updateRecord(post, params)
.then(response => {
swal({
title: 'Success',
text: `${currentUser.username} Your post has been updated!`,
type: 'success'
});
})
.catch(err => {
console.log(err);
});
}
deleteRecord() {
const { id } = this.props.match.params;
const post = this.props.posts[id];
const { currentUser } = this.props.user;
if (currentUser.id !== post.profile.id) {
swal({
title: 'Oops...',
text: 'Must be owner of post',
type: 'error'
});
return;
}
this.props
.deleteRecord(post)
.then(() => {
this.props.history.push('/');
swal({
title: 'Post Delete',
text: 'Please create a new post',
type: 'success'
});
})
.catch(err => {
console.log(err);
});
}
render() {
const { id } = this.props.match.params;
const post = this.props.posts[id];
const { currentUser } = this.props.user;
if (post == null) {
return <div />;
}
return (
<div>
<div className="jumbotron">
<h1 className="display-3">{post.title}</h1>
<div className="row" style={{ marginBottom: '25px' }}>
<img className="img-fluid mx-auto" src={`${post.image}`} style={{ maxHeight: '400px' }} />
</div>
<p className="lead">{post.text}</p>
<hr className="my-4" />
{post.video == undefined ? null : (
<div className="row justify-content-center">
<div className="col-8">
<div className="lead" style={{ marginBottom: '25px' }}>
<div className="embed-responsive embed-responsive-16by9">
<video style={{ background: 'black' }} width="800" controls loop tabIndex="0">
<source src={post.video} type={post.videoType} />
Your browser does not support HTML5 video.
</video>
</div>
</div>
</div>
</div>
)}
<div className="lead">
<Link to={`/profile/${post.profile.id}`}>
<button className="btn btn-secondary btn-lg">{post.profile.username}</button>
</Link>
<p style={{ marginTop: '10px' }}>{DateUtils.relativeTime(post.timestamp)}</p>
</div>
{currentUser.id !== post.profile.id ? null : (
<div className="row justify-content-end">
<div className="col-md-2">
<button
onClick={() => {
this.setState({ editShow: !this.state.editShow });
}}
className="btn btn-success"
>
Edit
</button>
</div>
<div className="col-md-2">
<button onClick={this.deleteRecord.bind(this)} className="btn btn-danger">
Delete
</button>
</div>
</div>
)}
</div>
{this.state.editShow === false ? null : (
<div>
<UpdateRecord onCreate={this.updateRecord.bind(this)} currentRecord={post} />
</div>
)}
<div>
<Reply postId={post.id} />
</div>
</div>
);
}
}
const stateToProps = state => {
return {
posts: state.post,
user: state.user
};
};
const dispatchToProps = dispatch => {
return {
getRecord: id => dispatch(actions.getRecord(id)),
updateRecord: (entity, params) => dispatch(actions.updateRecord(entity, params)),
deleteRecord: entity => dispatch(actions.deleteRecord(entity))
};
};
export default connect(stateToProps, dispatchToProps)(Post);
Upvotes: 2
Views: 3622
Reputation: 11930
Take a look here
case constants.RECORD_DELETED:
const newState = {
...state,
all: state.all.filter(item => item.id !== action.data.id)
};
delete newState[action.payload.id];
return newState;
You are using action.data
when filtering, and action.payload
when deleting from object
Upvotes: 2