简体   繁体   中英

How to force react component to re-render after deletion

I have a react component which renders a list of covers and a button to delete the book from the list onClick. I'm passing in the delete action via map dispatch to props and the bookshelf info via map state to props. The delete action is successfully deleting the book from the database and is hitting my reducer. But even though the state updates, the book list component does not re-render (the deleted book doesn't disappear unless I reload).

 import React from 'react'; import { Link, withRouter } from 'react-router-dom'; import {CarouselProvider, Slider, Slide, ButtonBack, ButtonNext, Image, Dot} from 'pure-react-carousel'; class BookshelfIndexItem extends React.Component { constructor(props){ super(props); } render() { return( <div> <h3 className='shelf-title'>{this.props.bookshelf.name}</h3> <CarouselProvider naturalSlideWidth={135} naturalSlideHeight={250} totalSlides={this.props.bookshelf.book_ids.length} visibleSlides={3}> <Slider style={{height: '240px', display: 'flex', 'justifyContent': 'space-between'}}> {this.props.bookshelf.book_ids.map((id, index) =>(<Slide index={index} key={id} style={{'width': '150px','display': 'flex','alignItems': 'center', 'margin': '0 50px'}}> <Link to={`/books/${id}`}> <Image style={{height: '200px', width: '140px'}} src ={this.props.books[id].image_url}></Image> </Link> <button style={{height: '35px', 'marginLeft': '55px', 'marginTop': '5px'}} onClick={() => this.props.deleteBookFromBookshelf({book_id: id, bookshelf_id: this.props.bookshelf.id})}> X </button> </Slide>))} </Slider> <div className='slider-button-container'> <ButtonBack className='slider-button'>back</ButtonBack> <ButtonNext className='slider-button'>next</ButtonNext> </div> </CarouselProvider> </div> ); } } export default withRouter(BookshelfIndexItem); 

I've tried a few of the lifecycle methods, such as fetching all the bookshelves in ComponentWillReceiveProps, but no change.

I have a strong suspicion I know what's up - any chance you're pushing to a copy of the array you're keeping in state and then setting state to that? When you push to an array (or add an item to a set or anything similar), you still end up with the same list object in memory (though with different contents). React is checking to see if there's a new list, and it sees the old list, sees the new list, and says "hey those are the same object in memory, so since they're the same I don't need to even trigger a shouldComponentUpdate .

I've produced a minimal example of this behavior so you can see it in action: https://codesandbox.io/s/nrk07xx82j

If you hit the first button, you can see in the console that the new state is in fact correct, but the rendered list never updates (because of what I discussed above).

However, if you use array destructuring ( [...list] ), you end up returning the same array contents , but in a new array object, triggering a React update.

Hope that helps!

ninja edit: realizing I could be more specific since you're talking about deleting items - Array.pop and Array.splice() both behave in the same way, you're still dealing with the same object in memory and thus won't be triggering a component update.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM