Reactjs 当我从状态中删除项时,组件不会重新加载,但当我添加项时,组件会重新加载

Reactjs 当我从状态中删除项时,组件不会重新加载,但当我添加项时,组件会重新加载,reactjs,Reactjs,我有一个喜欢的方法,它根据返回值检查数组中的现有项,组件配方有条件地显示。这里我注意到的是,当我向数组(likedList)子组件重新渲染器中添加一个项时,条件是check,但当我删除项时,即使使用了setState,也不会重新渲染 class App extends Component { state = { result:[], recipe:{}, isActive:"47746", addToShopping: [], likedList:[

我有一个喜欢的方法,它根据返回值检查数组中的现有项,组件配方有条件地显示。这里我注意到的是,当我向数组(likedList)子组件重新渲染器中添加一个项时,条件是check,但当我删除项时,即使使用了setState,也不会重新渲染


class App extends Component {
  state = {
    result:[],
    recipe:{},
    isActive:"47746",
    addToShopping: [],
    likedList:[]
  }

  setActiveId=(id)=>{
    this.getRecipe(id)
  }

  pushToLikeList = () => {
    // if id is in likeList then remove
    // if id not in likeList then add
    if(this.state.likedList.findIndex(el=>el.recipe.recipe_id===this.state.isActive) === -1){
      this.setState(prevState => {
        return {
          likedList: [prevState.recipe, ...prevState.likedList]
        }
      })
    }else{
      this.setState(prevState=>{
        const index = prevState.likedList.findIndex(el=>el.recipe.recipe_id===prevState.isActive);
        prevState.likedList.splice(index,1)
        return{
          likedList:prevState.likedList
        }
      })

    }


  }
  Liked=()=>{
    return (this.state.likedList.findIndex(el=>el.recipe.recipe_id===this.state.isActive) !== -1)
  }
  render() {

    return (
      <div className="App">

        <Recipe_serving 
        isActive={this.state.isActive}
        likedList={this.state.likedList}
        pushToLikeList={this.pushToLikeList}
        Liked={this.Liked}
        />
      </div>
    );
  }
}

const Recipe_serving = (props)=>{

    return(
        <div>
            <button className="recipe__love" onClick={props.pushToLikeList}>
                <svg className="header__likes">
                    <use href={props.Liked?"img/icons.svg#icon-heart":"img/icons.svg#icon-heart-outlined"}></use>
                </svg>
            </button>
        </div>
    )
}

类应用程序扩展组件{
状态={
结果:[],
配方:{},
isActive:“47746”,
地址:[],
likedList:[]
}
setActiveId=(id)=>{
此.getRecipe(id)
}
pushToLikeList=()=>{
//如果id在likeList中,则删除
//如果id不在likeList中,则添加
if(this.state.likedList.findIndex(el=>el.recipe.recipe\u id==this.state.isActive)=-1){
this.setState(prevState=>{
返回{
likedList:[prevState.recipe,…prevState.likedList]
}
})
}否则{
this.setState(prevState=>{
const index=prevState.likedList.findIndex(el=>el.recipe.recipe\u id==prevState.isActive);
prevState.likedList.splice(索引,1)
返回{
likedList:prevState.likedList
}
})
}
}
喜欢=()=>{
return(this.state.likedList.findIndex(el=>el.recipe.recipe\u id==this.state.isActive)!=-1)
}
render(){
返回(
);
}
}
const Recipe_serving=(道具)=>{
返回(
)
}

关键在于React检查道具/状态的变化很肤浅——任何子对象(和数组,因为它们是对象)都是通过引用而不是通过值来检查的

使用spread操作符添加项时,实际上是通过克隆当前数组来创建一个全新的数组,因此React会注意到这一点并触发重新渲染器。但是,当您删除该项时,它是不同的,因为
splice
在适当的位置工作,并且对数组的引用保持不变

如何解决这一问题:

  • 在使用
    splice
    删除项目之前,使用
    slice
    克隆
    prevState.likedList

  • 使用
    filter
    创建一个包含除一个元素之外的所有现有元素的新数组

  • 使用排列运算符,例如:

  • 最后,您可以在设置状态后对组件执行
    forceUpdate()
    操作(不推荐,因为它会破坏语义,但可能会)

  • 关键是React检查道具/状态的变化只是肤浅的——任何子对象(和数组,因为它们是对象)都是通过引用而不是通过值来检查的

    使用spread操作符添加项时,实际上是通过克隆当前数组来创建一个全新的数组,因此React会注意到这一点并触发重新渲染器。但是,当您删除该项时,它是不同的,因为
    splice
    在适当的位置工作,并且对数组的引用保持不变

    如何解决这一问题:

  • 在使用
    splice
    删除项目之前,使用
    slice
    克隆
    prevState.likedList

  • 使用
    filter
    创建一个包含除一个元素之外的所有现有元素的新数组

  • 使用排列运算符,例如:

  • 最后,您可以在设置状态后对组件执行
    forceUpdate()
    操作(不推荐,因为它会破坏语义,但可能会)
  • …prevState.likedList.slice(索引+1,-1)应为…prevState.likedList.slice(索引+1),因为slice排除了end IndexHanks,已修复(无法立即测试)…prevState.likedList.slice(索引+1,-1)应为…prevState.likedList.slice(索引+1),因为slice排除了end IndexHanks,已修复(无法立即测试).
    return {
        likedList: [...prevState.likedList.slice(0, index), ...prevState.likedList.slice(index + 1)]
    }