pri
pri

Reputation: 630

all Images gets deleted instead of that particular image whose delete icon is clicked in reactjs

In my rent detail editing page, there is an image upload for user updating their images or remove previously uploaded images which are fetched from previousFile() and can further add images. Further added images are shown from onDrop() and showFiles(). I have defined handleRemove() for removing the images but they are not working properly.All images gets deleted instead of that particular image which user want to delete. What might be the reason for this?

enter image description here

Code is shortened

export default class RoomDetail extends Component{
    constructor(props){
        super(props);
        this.state = { rooms:[], isEditing:false };
        this.pk = this.props.data.pk;
    }

    componentDidMount(newUser){
        $.ajax({
            url:'/api/rentals/'+this.props.data.pk+'/',
            type:'put',
            contentType: "application/json",
            data:JSON.stringify(newUser),
            success: (data) => {
                console.log('data',data);
              },
              error: (xhr, status, err) => {
                console.error(xhr, status, err.toString());
              }
            });
    }

    componentWillMount(){
        this.loadRoomFromServer();
    }

    loadRoomFromServer(){
        $.ajax({
            url:'/api/rentals/'+this.props.data.pk,
            dataType:'json',
            success: (data) => {
                console.log('data',data);
                this.setState({rooms: data});
              },
              error: (xhr, status, err) => {
                console.error(xhr, status, err.toString());
              }
            });
    }

     handleRemove(id){
      const files = this.state.rooms.gallery.slice();
      this.setState({rooms:files.splice(id,1)});
     }

    renderRoomDetailSection(){
      let url = this.pk;
      let imageFile;
        let firstImage;
        if(this.state.rooms.gallery){
            firstImage = this.state.rooms.gallery[0].image;
            console.log('firstImage', firstImage);
            imageFile = _.map(this.state.rooms.gallery, (image) => {
            return(
                    <div className="col-md-3">
                        <img src={image.image} key={image.id} className="img-fluid img-rounded" />
                    </div>
                );
            });
        }
        if (this.state.isEditing ){
            return(
                    <EditRent 
                        ownerName={this.state.rooms.ownerName}
                        email = {this.state.rooms.email}
                        phoneNumber = {this.state.rooms.phoneNumber}
                        image = {this.state.rooms.gallery}
                        onRemove = {this.handleRemove.bind(this)}
                        pk={this.props.data.pk} />
                )
        }
                return(
                        <div className="detailListing">
                         here is the rent details 
                       </div>
                )
    }

    renderUserAction(){
        if ( this.state.isEditing ){
            return(
                    save and cancel button is here
                );

        }

        return(
                <div className = "buttons">
                 edit button is here
                </div>
            );
        }

    render() {
        return (
            <div className = "newRoomDetail" >
                 { this.renderRoomDetailSection() }
                 { this.renderUserAction() }
            </div>
        );
    }
    }

var fieldValues = {
  ownerName:'name',
  email:'[email protected]',
  phoneNumber:'9842333333'
}


class EditRent extends React.Component{
 constructor(props,context) {
        super(props,context);
        this.state = {
            step: 1
        };
        this.pk = this.props.pk;
    }

  saveValues(field_value) {
    return function() {
      fieldValues = Object.assign({}, fieldValues, field_value)
    }()
  }

  nextStep(step) {
    var step = this.state.step;
    var newStep = step+1;
    this.setState({step:newStep});
  }

  previousStep(step) {
    var step = this.state.step;
    var newStep = step-1
    this.setState({
      step : newStep
    });
  }

  showStep() {
  switch (this.state.step) {
    case 1:
      return <RenderPersonalInfo fieldValues={fieldValues}
                            ownerName={this.props.ownerName}
                            email={this.props.email}
                            phoneNumber={this.props.phoneNumber}
                            nextStep={this.nextStep.bind(this)}
                            previousStep={this.previousStep.bind(this)}
                            saveValues={this.saveValues.bind(this)} />
    case 2:
      return <RenderPhotos fieldValues={fieldValues}
                           image={this.props.image}
                           nextStep={this.nextStep.bind(this)}
                           previousStep={this.previousStep.bind(this)}
                           imageRemove={this.props.onRemove}
                           pk={this.props.pk} />
  }
}

  render() {

    return (
      <main className="container">
        <div className="row">
          <div className="col-sm-12">
            <span className="progress-step">Step {this.state.step}</span>
            </div>
        </div>
        <div className="container">
          <div className="row">
            {this.showStep()}
          </div>
        </div>
      </main>
    )
  }
};

 let image = [];
 class RenderPhotos extends React.Component {
    constructor(props, context) {
        super(props, context);
        this.state = {
            files: []
        };
    }

    handleClick(image){
      this.props.imageRemove(image);
    }

    onDrop(files) {
      console.log('Received files: ', files);
      this.setState({
          files: files
      });

      image = new FormData(files);
      $.each(files,function(i,file){
        image.append('image',file);
      });

    }

    previousFile(){
      return(
          <ul className="gallery">
            {
             _.map(this.props.image, (image,idx) => {
                      return(
                          <li className="col-md-3" key={idx}>
                            <span className="remove"><i onClick= onClick= {this.handleClick.bind(this,image)} className = "fa fa-times" aria-hidden="true"></i></span>
                            <img src={image.image} key={image.id} className="img-fluid img-rounded" />
                          </li>
                        )
                    })
            }
          </ul>
        )
    }

    showFiles() {
        const { files } = this.state;
        if (!files.length) {
            return null;
        }
        return (
            <div>
                <h3>Dropped files: </h3>
                <ul className="gallery">
                    {
                        _.map(files, (file, idx) => {
                            return (
                                <li className="col-md-3" key={idx}>
                                    <img src={file.preview} width={200}/>
                                    <div>{file.name}</div>
                                </li>
                            )
                        })

                    }
                </ul>
            </div>
        );
    }

    render() {
      return (
           <div>
                <div className="col-md-12">
                <form method="POST" encType="multipart/form-data">
                <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}"/>
                  <Dropzone onDrop={this.onDrop.bind(this)}
                          style={style}
                          activeStyle={activeStyle}
                          accept="image/*">
                    Try dropping some files here, or click to select files to upload.
                </Dropzone>
              </form>
                { this.previousFile() }
                { this.showFiles() }

              </div>
              <div className="row continueBtn text-right">
                    <button className="btn how-it-works pull-left" onClick={this.props.previousStep.bind(this)}><i className="fa fa-hand-o-left"></i></button>
                    <button className="btn how-it-works pull-right" onClick={this.nextStep.bind(this)}><i className="fa fa-floppy-o"></i></button>
               </div>
            </div>

      );
    }
}

Remove part is in RenderPhotos component.

Upvotes: 0

Views: 598

Answers (1)

Edvin Wennerdahl
Edvin Wennerdahl

Reputation: 694

The problem here is that you try to remove images that comes from the props (previousFile) by setting them in the local state. That approach would work if you would render the images from the local state instead but what you do is that you render directly from props which will cause React to not see any changes. To make the image removal to work you will need to move the removal logic to the parent component and supply the child with a function to trigger the deletion.

class Parent extends Component {
  constructor() {
    this.state = {
      files: []
    };
  }

  handleRemove(id) {
    const files = this.state.files.slice();
    this.seState({
      files: files.splice(id, 1)
    });
  }

  render() {
      return <Files files={this.state.files} onRemove={this.handleRemove.bind(this)} />;
    }
}

function handleClick(id, props) {
  props.handleRemove(id);
}

function Files(props) {
    return (
      <ul>
        {props.files.map(
         (file, key) => <li key={key} onClick={handleClick.bind(this, key, props)}>{file.name}</li>
        )}
      </ul>
    );
}

Upvotes: 1

Related Questions