Nosnetrom
Nosnetrom

Reputation: 161

A record is being deleted, but why is .setState not working?

I think I'm having a fundamental issue understanding state and props... I have an array of records, and when I console.log the array it returns the correct records, but .setState is not changing the returned records in the UI. I wonder if perhaps handleCommentDelete needs to be moved to the parent component? Here's the parent:

import React from 'react';
import { render } from 'react-dom';

import CommentForm from './CommentForm';
import CommentList from './CommentList';


class CommentBox extends React.Component {
    constructor(props) {
        super(props);
        this.state = { data: [] };
        this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
    }
    componentDidMount() {
        this.loadCommentsFromServer();
        window.setInterval(
            () => this.loadCommentsFromServer(),
            this.props.pollInterval,
        );
    }
    handleCommentSubmit(comment) {
        const comments = this.state.data;
        comment.Id = comments.length + 1;
        const newComments = comments.concat([comment]);
        this.setState({ data: newComments });

        const data = new FormData();
        data.append('Id', comment.Id);
        data.append('Name', comment.Name);
        data.append('Phone', comment.Phone);
        data.append('Email', comment.Email);

        const xhr = new XMLHttpRequest();
        xhr.open('post', this.props.submitUrl, true);
        xhr.onload = () => this.loadCommentsFromServer();
        xhr.send(data);
    }
    loadCommentsFromServer() {
        const xhr = new XMLHttpRequest();
        xhr.open('get', this.props.url, true);
        xhr.onload = () => {
            const data = JSON.parse(xhr.responseText);
            this.setState({ data: data });
        };
        xhr.send();
    }
    render() {
        return (
            <div className="row padBottom_10">
                <div className="col-md-12">
                    <CommentForm onCommentSubmit={this.handleCommentSubmit} />
                </div>
                <div className="col-md-12">
                    <div className="commentBox border borderBorderGrey highlightPrimaryGrey">
                        <CommentList data={this.state.data} />
                    </div>
                </div>
            </div>

        );
    }
}

export default CommentBox;

...and here's the child component, where I'm trying to delete a record.

import React from 'react';
import { render } from 'react-dom';

class CommentList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: [{}]
        };
        this.handleCommentDelete = this.handleCommentDelete.bind(this);
    }
    handleCommentDelete(id) {
        console.log(this.props.data); // returns n records
        let comments = [...this.props.data];
        this.setState({
            data: comments.filter(comment => comment.Id !== id)
        });
        console.log(comments.filter(comment => comment.Id !== id)); // returns n - 1 records
    }
    render() {
        return (
            <table className="commentList react-bs-table">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Phone</th>
                        <th>Email</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    {
                        this.props.data.map((comment, i) => {
                            return (
                                <tr className="comment" key={i}>
                                    <td className="commentId">{comment.Id}</td>
                                    <td className="commentName">{comment.Name}</td>
                                    <td className="commentPhone">{comment.Phone}</td>
                                    <td className="commentEmail">{comment.Email}</td>
                                    <td className="commentCRUD">
                                        <a onClick={() => this.handleCommentDelete(comment.Id)}>
                                            <i className="fa fa-trash" />
                                        </a>
                                    </td>
                                </tr>
                            );
                        })
                    }
                </tbody>
            </table>
        );
    }
}

export default CommentList;

I'm really beating my head against the wall to understand this... thanks in advance for any help!

Upvotes: 0

Views: 99

Answers (1)

amcquaid
amcquaid

Reputation: 539

handleCommentDelete should be in the parent component. You can pass the function down to the child from the parent as a prop.

Pass a function to a child component

<CommentList data={this.state.data} handleCommentDelete={this.handleCommentDelete} />

Parent function

handleCommentDelete = (id) => {
    this.setState({
        data: this.state.data.filter(comment => comment.Id !== id)
    });
}

Reference prop function

<a onClick={() => this.props.handleCommentDelete(comment.Id)}>

You are mixing state and props in the child when it should just be props. Pass handleCommentDelete as a prop to the child, call it with this.props.handleCommentDelete(id), and update the state in the parent to reflect the delete. This will then rerender the child with the new list of comments.

Upvotes: 1

Related Questions