【问题标题】:Getting error TypeError: Cannot read property 'id' of undefined using React/Redux action出现错误类型错误:无法使用 React/Redux 操作读取未定义的属性“id”
【发布时间】:2017-10-23 22:51:51
【问题描述】:

我正在使用 react/redux,并且在使用操作调用 deleteRequest 后发生错误。减速器从数组中删除该项目,我认为这就是发生这种情况的原因,但我应该更改位置,因此它不应该再呈现此页面。

直接错误来自于 catch 块中 this.props.deleteRecord 下方的 Post 组件。

我也在使用 turbo,这就是我创建 deleteRequest 和存储数据的方式。如果您需要参考这里是文档。 https://www.turbo360.co/docs

减速机:

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;
  }
};

组件:

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);

【问题讨论】:

    标签: javascript reactjs redux


    【解决方案1】:

    看这里

    case constants.RECORD_DELETED:
      const newState = {
        ...state,
        all: state.all.filter(item => item.id !== action.data.id)
      };
      delete newState[action.payload.id];
    
      return newState;
    

    过滤时使用action.data,从对象中删除时使用action.payload

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-25
      • 1970-01-01
      • 2019-02-28
      • 2020-07-22
      • 2020-03-03
      • 1970-01-01
      • 1970-01-01
      • 2018-04-29
      相关资源
      最近更新 更多