How to handle Spam Deleting in ReactJs

566 Views Asked by At

I have a list of items that each have a trash can beside them(ie delete button). Since there are so many possible results I display 25 results and then page the rest(when a user clicks the next page button at this time I get the next results).

However the problem that I am facing is once they delete a item, if there are still items in the database I want to retrieve their next item.

So 30 items belong to this user, they see 25 and if they delete one, the next item(item 26) gets pulled from the database and shown.

I don't think this would be hard to achieve the problem happens if they want to delete 5 items and click each after each other, I am scared a race condition will happen and instead of pulling item26, item27,item28,item29,item30, it may pull item26 x 5.

The only idea I can come up with is that I pull more than I show, if I show 25 records I pull 35 records and then keep refilling that bucket after each one gets deleted.

However I not sure how I would replenish the bucket of extras and scenarios on how to handle if there is not enough items to replenish the bucket.

I am using Reactjs, Mobx and Mobx State Tree.

I don't have any code yet as I no clue which way to go yet.

1

There are 1 best solutions below

6
On

This is what I Would do:

  1. Create an array within the state to hold currently deleting items
  2. Within my delete function Check if the item is currently being deleted
  3. If is being deleted do nothing
  4. If is not, add the item to the array, call axios.delete() and then remove the item from the array

class PreventSpam extends React.Component {
  constructor(props){
    super(props);
    //Example data
    const exampleList = [{id: 1, name: "One"},
                         {id: 2, name: "Two"},
                         {id: 3, name: "Three"},
                         {id: 4, name: "Four"}]
    //State of the current component
    this.state={
      Deleting: [],
      items: exampleList
    }
    
    this.deleteItem = this.deleteItem.bind(this);
    this.loadNext = this.loadNext.bind(this);
  }
  
  deleteItem(item){
     //Remove element from my state
     let newItems = this.state.items.filter(it=> it.id !== item.id);
     this.setState({
       items: newItems
     });
     
     //If this items is currently being deleted, return;
     if(this.state.Deleting.indexOf(item.id) !== -1){
       console.log("wait for this deletion to complete")
       return;
     }
     
     //Add the item to the deleting array
     this.setState((state,props)=> ({
       Deleting: [...state.Deleting, item.id]
     }));
     
     //call delete with axios
     axios.delete(`url/${item.id}`).then(()=>{
        //Delete successful, update the deleting list
          let newDeleting = [...this.state.Deleting];
          let deletedIndex = newDeleting.indexOf(item.id);
          newDeleting.splice(deletedIndex, 1);
          this.setState({Deleting: newDeleting});
       
          
          //Load next item
       loadNext();
     }).catch(error => {
        //Opt 1: add the item back to the state on error
          //Opt 2: alert the user
          //Opt 3: ?????
     })
  }
  
  //Loads the 25th or last item on the database
  loadNext(){
    axios.get("apiCall").then(response => {
      let newItem = response.data;
    });
  }
  render() {
    const {items} = this.state;
    return (<div>
      <table>
         <tbody>
           {items.map((item,index)=>{
             return (
               <tr key={index}>
                 <td>{item.id}</td>
                 <td>{item.name}</td>
                 <td><button onClick={() => this.deleteItem(item)}>Delete</button></td>
               </tr>
             )
            })
           }
        </tbody>
      </table>
      
    </div>);
  }
}

ReactDOM.render(
  <PreventSpam  />,
  document.getElementById('container')
);
<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="container">
    <!-- This element's contents will be replaced with your component. -->
</div>