[javascript] 구성 요소 상태의 배열에서 요소 제거

구성 요소 상태의 배열에서 요소를 제거하는 가장 좋은 방법을 찾으려고합니다. this.state변수를 직접 수정해서는 안되므로 배열에서 요소를 제거하는 더 나은 방법 (더 간결한 방법)이 있습니까?

  onRemovePerson: function(index) {
    this.setState(prevState => { // pass callback in setState to avoid race condition
      let newData = prevState.data.slice() //copy array from prevState
      newData.splice(index, 1) // remove element
      return {data: newData} // update state
    })
  },

감사합니다.

업데이트

setState에서 콜백을 사용하도록 업데이트되었습니다. 업데이트하는 동안 현재 상태를 참조 할 때 수행해야합니다.



답변

내가 본 가장 깨끗한 방법은 다음과 filter같습니다.

removeItem(index) {
  this.setState({
    data: this.state.data.filter((_, i) => i !== index)
  });
}


답변

에서 update()불변성 도우미를react-addons-update 사용할 수 있습니다 .

this.setState(prevState => ({
  data: update(prevState.data, {$splice: [[index, 1]]})
}))


답변

this.state내부 참조 setState()는 권장하지 않습니다 ( 상태 업데이트는 비동기 일 수 있음 ).

문서 setState()는 업데이트가 발생할 때 prevState가 런타임에 전달되도록 콜백 함수와 함께 사용 하는 것이 좋습니다 . 이것이 다음과 같이 보입니다 :

ES6없이 Array.prototype.filter 사용

removeItem : function(index) {
  this.setState(function(prevState){
    return { data : prevState.data.filter(function(val, i) {
      return i !== index;
    })};
  });
}

ES6 화살표 함수와 함께 Array.prototype.filter 사용

removeItem(index) {
  this.setState((prevState) => ({
    data: prevState.data.filter((_, i) => i !== index)
  }));
}

불변 헬퍼 사용하기

import update from 'immutability-helper'
...
removeItem(index) {
  this.setState((prevState) => ({
    data: update(prevState.data, {$splice: [[index, 1]]})
  }))
}

스프레드 사용

function removeItem(index) {
  this.setState((prevState) => ({
    data: [...prevState.data.slice(0,index), ...prevState.data.slice(index+1)]
  }))
}

사용 된 기술에 관계없이 각각의 경우 에 이전에 대한 객체 참조가 아닌this.setState() 콜백이 전달 된다는 점에 유의하십시오 .this.state


답변

다음은 ES6 스프레드 구문을 사용하여 상태의 배열에서 요소를 제거하는 방법입니다.

onRemovePerson: (index) => {
  const data = this.state.data;
  this.setState({
    data: [...data.slice(0,index), ...data.slice(index+1)]
  });
}


답변

이 질문 에 @pscl 이 이미 올바르게 대답 했지만 다른 사람이 내가 한 것과 같은 문제가 발생하는 경우를 대비 하여 여기에 차임하고 싶습니다 . 4 가지 방법 중 나는 간결하고 외부 라이브러리에 대한 의존성이 없기 때문에 화살표 함수와 함께 es6 구문을 사용하기로 선택했습니다.

ES6 화살표 함수와 함께 Array.prototype.filter 사용

removeItem(index) {
  this.setState((prevState) => ({
    data: prevState.data.filter((_, i) => i != index)
  }));
}

보시다시피 , 필자의 경우 문자열 필드에서 색인을 검색했기 때문에 색인 유형 ( !==to !=) 을 무시하도록 약간 수정했습니다 .

클라이언트 측에서 요소를 제거 할 때 이상한 동작이 나타나는 경우 또 다른 유용한 점 은 배열의 색인을 요소의 키로 사용하지 않는 것입니다 .

// bad
{content.map((content, index) =>
  <p key={index}>{content.Content}</p>
)}

React가 변경 사항에서 가상 DOM과 차이점을 변경하면 변경된 내용을 결정하는 키를 살펴 봅니다. 따라서 인덱스를 사용하고 있고 배열에 적은 것이 있으면 마지막 인덱스를 제거합니다. 대신 콘텐츠의 ID를 키로 사용하십시오.

// good
{content.map(content =>
  <p key={content.id}>{content.Content}</p>
)}

위의 내용은 관련 게시물의 답변에서 발췌 한 것입니다 .

모두 행복한 코딩!


답변

색인없이 요소를 제거하려는 경우이 기능을 사용할 수 있습니다.

removeItem(item) {
  this.setState(prevState => {
    data: prevState.data.filter(i => i !== item)
  });
}


답변

위의 ephrion의 답변에 대한 언급에서 언급했듯이 filter ()는 이미 큰 것으로 판단되는 인덱스를 찾기 위해 반복되므로 특히 큰 배열의 경우 느릴 수 있습니다. 이것은 깨끗하지만 비효율적 인 솔루션입니다.

대안으로서, 원하는 요소를 간단히 ‘슬라이스’하고 단편들을 연결할 수있다.

var dummyArray = [];
this.setState({data: dummyArray.concat(this.state.data.slice(0, index), this.state.data.slice(index))})

도움이 되었기를 바랍니다!