I'm starting with react, and as an exercise I want to make a drag & amp image charger. Drop using components.
The problem is that when loading an image the RAM consumption of the navigator rises, but when dragging images again to the component, the memory consumption rises even though previously loaded images have already been deleted.
class ImagesLoader extends React.Component{
constructor(props){
super(props)
this.state = {images: []}
this.AddImages = this.AddImages.bind(this)
this.handleUpdateImages = this.handleUpdateImages.bind(this)
}
AddImages(e){
e.preventDefault()
let images= []
let files = e.dataTransfer.files
for(let i = 0; i < files.length;i++){
let file = files[i]
if(file.type.split('/')[0] === "image"){
let name = file.name.substring(0,file.name.lastIndexOf("."))
let newImage = {
title: name,
file: file,
category: 1
}
images.push(newImage)
}
}
this.setState({
images: images
})
}
handleUpdateImages(upImages){
this.setState({images: upImages})
}
render(){
return(
<div
className="ImagesLoader">
<Droparea onDropFiles={this.AddImages}/>
<Previews
images={this.state.images}
onUpdateImages={this.handleUpdateImages}
/>
</div>
)
}
}
class Droparea extends React.Component{
constructor(props){
super(props)
this.handleDragOver = this.handleDragOver.bind(this)
this.handleDragLeave = this.handleDragLeave.bind(this)
}
handleDragOver(e){
e.preventDefault()
let target = e.target
target.classList.add('over')
}
handleDragLeave(e){
e.preventDefault()
let target = e.target
target.classList.remove('over')
}
render(){
return(
<div
className="Droparea"
onDragOver={this.handleDragOver}
onDragLeave={this.handleDragLeave}
onDrop={this.props.onDropFiles}>
<span className="Droparea-text"> Drag your elements Here. </span>
</div>
)
}
}
class Previews extends React.Component{
constructor(props){
super(props)
this.handleChangeItem = this.handleChangeItem.bind(this)
}
handleChangeItem(oldItem,prop,newValue){
let images = this.props.images
images.map((image) => {
if(image === oldItem){
image[prop] = newValue
}
})
this.props.onUpdateImages(images)
}
render(){
let images = this.props.images
const imageList = images.map(image =>
<PreviewItem
key={image.file.name}
image={image}
onChangeItem={this.handleChangeItem}/>
)
return(
<ul className="Previews">
{imageList}
</ul>
)
}
}
class PreviewItem extends React.Component{
constructor(props){
super(props)
this.handleChangeTitle = this.handleChangeTitle.bind(this)
this.handleChangeCategory = this.handleChangeCategory.bind(this)
}
handleChangeTitle(value){
this.props.onChangeItem(this.props.image,'title',value)
}
handleChangeCategory(value){
this.props.onChangeItem(this.props.image,'category',value)
}
render(){
return(
<li className="Preview-item">
<PreviewItemImg image={this.props.image}/>
<PreviewItemForm
image={this.props.image}
onChangeTitle={this.handleChangeTitle}
onChangeCategory={this.handleChangeCategory}
/>
</li>
)
}
}
class PreviewItemImg extends React.Component{
constructor(props){
super(props)
this.state = {image: this.props.image, src: false}
this.getImage().then(src => {
this.setState({src: src.src})
})
}
getImage(){
return new Promise((resolve,reject) => {
let image = this.props.image.file
let fileReader = new FileReader()
fileReader.onload = function(){
let base64 = this.result
let img = new Image()
img.onload = function(){
resolve(this)
}
img.src = base64
}
fileReader.readAsDataURL(image)
})
}
render(){
if(!this.state.src){
return null
}
return(
<div className="Preview-item-img">
<img className="Item-img" src={this.state.src}/>
</div>
)
}
}
class PreviewItemForm extends React.Component{
constructor(props){
super(props)
let title = (this.props.image.file.name === this.props.image.name)
? this.props.image.file.name
: this.props.image.title
this.state = {
title: title,
category: this.props.image.category
}
this.handleChangeTitle = this.handleChangeTitle.bind(this)
this.handleChangeCategory = this.handleChangeCategory.bind(this)
}
handleChangeTitle(e){
let value = e.target.value
this.setState({title: value})
this.props.onChangeTitle(value)
}
handleChangeCategory(e){
let value = e.target.value
this.setState({category: value})
this.props.onChangeCategory(value)
}
render(){
const categories = [
{value: 1, name: 'Animals'},
{value: 2, name: 'Cgi'},
{value: 3, name: 'Landscapes'},
{value: 4, name: 'Women'}
]
return(
<form className="Preview-item-form">
<input type="text"
placeholder="Insert title"
onChange={this.handleChangeTitle}
value={this.state.title}
/>
<select value={this.state.category}
onChange={this.handleChangeCategory}>
{
categories.map((c) =>
<option
key={c.value}
value={c.value}>
{c.name}
</option>
)
}
</select>
</form>
)
}
}
ReactDOM.render(
<ImagesLoader />,
document.getElementById('root')
);
.ImagesLoader {
font-family: Ubuntu;
width: 100%;
}
.ImagesLoader .Droparea {
display: flex;
flex-flow: row wrap;
justify-content: center;
align-items: center;
min-height: 300px;
height: 30%;
width: 100%;
background-color: #1a1a1a;
color: #808080;
transition: all 0.2s ease-in;
}
.ImagesLoader .Droparea.over {
color: #1a1a1a;
background-color: #ff6347;
}
.ImagesLoader .Previews {
padding: 0;
margin: 0;
min-height: 600px;
width: 100%;
}
.ImagesLoader .Previews .Preview-item {
list-style-type: none;
margin: 0;
padding: 0;
border: dashed 1px #ff6347;
}
.Preview-item-img {
position: relative;
}
.Preview-item-img img {
position: relative;
max-width: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'>
</div>
What do you think is the cause of the problem regarding RAM?
NOTE:
If you observe any bad practice in my code please let me know,