1

I'm just learning react at the moment, I have built a layout page and then display images using a component. Inside the component, each image has a button. this button deletes the image from the API.

But although the API call is working, and the image is deleted from the database, its not removing that image component from the layout.

Im using axios to interact with the API. Any help would be greatly appreciated.

My layout code is as follows;

import React, { Component } from "react";
import axios from 'axios';
import ImageComponent from './components/ImageComponent';

class ImageOverview extends Component {
    constructor(props) {
        super(props);
        this.state = {
            imageData: []
        };
    }

    componentDidMount() {
        axios.get('http://api.com/getAllImages')
            .then(res => {
                const imageData = res.data;
                this.setState({ imageData });
            })
    }

    render() {
        return (
            <>
                <div className="content">
                    <Row>
                        <Col lg="12">
                            <Card>
                                <CardBody>
                                    <Row>
                                        { this.state.imageData.map(image =>
                                            <ImageComponent
                                                key={image.id}
                                                image={image}
                                            />
                                        )}
                                    </Row>
                                </CardBody>
                            </Card>
                        </Col>
                    </Row>
                </div>
            </>
        )
    }
}

export default ImageOverview;

and my component code is here;

import React, { Component } from "react";
import axios from 'axios';

class ImageComponent extends Component {

    deleteImage(id)
    {
        axios.delete('http://api.com/deleteimage' + id)
            .then(res => {
                console.log(res);
            })
    }

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

        return (
            <>
                <Col className="col-xs-6 col-xs-6">
                    <Card className="h-80">
                        <CardImg top width="100%" src={'http://imagelocation.com/' + image.filename} alt="Card image cap" />
                        <CardBody>
                            <Button color="danger" size="sm" onClick={() => this.deleteImage(image.id)}><i className="icon-simple-remove" /> Delete</Button>
                        </CardBody>
                    </Card>
                </Col>
            </>
        )
    }
}

export default ImageComponent;
1
  • 1
    After successful delete you need to remove the given image from this.state.imageData array of parent component too. Since you can't change state of parent from child, move the deleteImage method to parent and pass it down as prop to ImageComponent. Once you have lot of data and components and it starts getting to complex to pass stuff down to child as props, you might wanna maintain a global state using Redux, but don't worry about it just yet. Commented Aug 27, 2019 at 8:12

2 Answers 2

2

You need to actually update the state belonging to the Layout component. Specifically, you need to delete the specific image from the imageData array. That will trigger a re-render of the component to reflect your changes.

In Layout.js, create an event-handler that will delete the specific image:

deleteImageInState = (id) => {
   const { imageData } = this.state
   const newImageData = imageData.filter((img) => img.id !== id)
   this.setState({
     imageData: newImageData
   })
}

The function above simply creates a new imageData list that will not include the image that was deleted.

Then pass that function down to your ImageComponent as a prop, like you have within the .map() logic.

<ImageComponent 
    key={image.id} 
    image={image} 
    deleteImageInState ={this.deleteImageInState}
/>

Lastly update the deleteImage function you defined in ImageComponent.js to call the prop change-handler upon deletion.

deleteImage = (id) => {
    axios.delete('http://api.com/deleteimage' + id)
        .then(res => {
            this.props.deleteImageInState(id)
        })
 }
Sign up to request clarification or add additional context in comments.

Comments

0

Add the deleteImage(id) method in the parent component ImageOverview and pass it as props to the child ImageComponent:

<ImageComponent key={image.id} image={image} deleteHandler={this.deleteImage.bind(this}} />

Inside the deleteImage(id) call this.setState() to trigger the re-render once the image has been deleted, this is what you were missing without the change in state through setState() the component won't re-render with the new data:

deleteImage(id)
    {
        axios.delete('http://api.com/deleteimage' + id)
            .then(res => {
                this.setState({}) //delete the image from imageData array
            })
    }

You can call the deleteImage(id) as follows in the child component:

<CardBody>
        <Button color="danger" size="sm" onClick={() => this.props.deleteHandler(image.id)}><i className="icon-simple-remove" /> Delete</Button> 
</CardBody>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.