Reputation: 653
I'm fairly new to react. What I'm trying to do is to delete a component from an array given an index when the "[x]" button is clicked. From what I understood react re-renders the Component whenever the state has changed.
The labels variable on the render() method is an array of components and also has other child components. When the user clicks the [x] on one of the components, it would pass the index of that to the class function closeLabelHandler() and assign the state objects, indexToDelete and isDeletingLabel to the index of the element and true, respectively.
Since I am changing a state object, I was thinking that this during the re-render an element would be deleted from the labels array but alas, it doesn't.
Here's my code:
import React, { Component } from 'react';
import "./ImageContainer.css";
import { Stage, Layer, Image, Tag, Text, Label } from 'react-konva';
import ToolsContainer from '../ToolsContainer/ToolsContainer';
class ImageContainer extends Component {
state = {
showImageContainer: true,
canvasHeight: 0,
canvasWidth: 0,
canvasImageUrl: "",
image: null,
commentsArray: [],
labelCount: 0,
isDeletingLabel: false,
indexToDelete: -1
}
componentDidMount() {
let stage = this.refs.stage
const imgObj = new window.Image();
imgObj.src = this.props.selectedImageURI
imgObj.onload = () => {
this.setState({ image: imgObj })
this.setState({ canvasWidth: imgObj.width, canvasHeight: imgObj.height });
let canvasImageUrl = stage.toDataURL();
this.setState({ canvasImageUrl: canvasImageUrl })
}
}
getLabelCount = (count) => {
this.setState({ labelCount: count })
}
displayContainerHandler = () => {
this.props.showImageContainer(!this.state.showImageContainer)
}
downloadImageHandler = () => {
let a = document.createElement('a');
a.href = this.state.canvasImageUrl.replace("image/png", "image/octet-stream");
a.download = 'shot.png';
a.click();
}
closeLabelHandler = (index) => {
this.setState({
isDeletingLabel: true,
indexToDelete: index
})
console.log("[closeLabelHandler] " + index)
}
render() {
console.log("[ImageContainer][render]" + this.state.commentsArray)
let labels = [];
for (let i = 0; i < this.state.labelCount; i++) {
labels.push(
<Label key={i} draggable={true} x={150 + i * 2} y={150 + i * 2} >
<Tag
fill="black"
pointerWidth={10}
pointerHeight={10}
lineJoin='round'
shadowColor='black'
/>
<Text
text="Insert Comment Here"
fontFamily='Calibri'
fontSize={18}
padding={5}
fill='white'
/>
<Text
text="[x]"
fontFamily='Calibri'
fontSize={18}
x={170}
fill='black'
onClick={() => this.closeLabelHandler(i)}
/>
</Label>
)
if (this.state.isDeletingLabel) {
labels.splice(this.state.indexToDelete, 1)
this.setState({
isDeletingLabel: false,
indexToDelete: -1
})
}
}
return (
<div className="ImageContainer" >
<button className="ImageContainer-close-button " onClick={this.displayContainerHandler}>[x]</button>
<Stage ref="stage" height={this.state.canvasHeight * .5} width={this.state.canvasWidth * .5} >
<Layer>
<Image image={this.state.image} scaleX={0.5} scaleY={0.5} />
{labels}
</Layer>
</Stage>
<ToolsContainer getLabelCount={count => this.getLabelCount(count)} />
<button className="pure-button" onClick={() => this.downloadImageHandler()}>Download</button>
</div>
)
}
}
Any help would be appreciated.
Upvotes: 1
Views: 82
Reputation: 627
This is a simple way to achive what you want. You should not change your state directly, it could cause inconsistency to your application.
import React, { Component } from "react";
class Books extends Component {
state = {
books: [{ id: 1, title: "Book 1" }, { id: 2, title: "Book 2" }]
};
handleDelete = book => {
const books = this.state.books.filter(b => b.id !== book.id);
this.setState({ books });
};
render() {
return (
<ul>
{this.state.books.map(book => (
<li key={book.id}>
{book.title}{" "}
<button onClick={() => this.handleDelete(book)}>x</button>
</li>
))}
</ul>
);
}
}
export default Books;
Upvotes: 2