programing

컴포넌트에 고유 키를 부여할 때 Math.random()을 사용하여 해당 키를 생성해도 될까요?

muds 2023. 3. 2. 22:44
반응형

컴포넌트에 고유 키를 부여할 때 Math.random()을 사용하여 해당 키를 생성해도 될까요?

문제는 다음과 같습니다.

수천 개의 요소 목록 형식의 데이터를 가지고 있습니다.그 중에는 중복되는 것도 있기 때문에, 중복되는 키가 있는 경우도 있습니다.수에 ID를 사용해도 요?Math.random()대??

제가 알기로는 키는 주로 컴포넌트를 구별하기 위해 반응으로 사용됩니다.내 코드에 있는 키와 전혀 관련이 없는 한, 이 일은 잘 될 거라고 생각해.중복되는 숫자가 없도록 하기 위해 두 개의 산술 난수를 서로 나누어 거의 확실하게 고유한 키를 얻는 것이 좋습니다.

이게 좋은 방법인가요?아무 걱정 없이 사용할 수 있나요?

컴포넌트의 키가 변경될 때마다 React는 현재 컴포넌트 인스턴스를 업데이트하지 않고 컴포넌트 인스턴스를 만듭니다.따라서 퍼포먼스를 위해 Math.random()을 사용하는 것은 최소한으로 말하면 최적이라고 할 수 없습니다.

또한 컴포넌트 목록을 정렬할 경우 인덱스를 로 사용하는 것은 도움이 되지 않습니다.React 조정자는 컴포넌트와 관련된 기존 DOM 노드를 이동할 수 없기 때문입니다.대신 각 목록 항목에 대해 DOM 노드를 다시 작성해야 합니다.이 경우에도 최적의 성능을 얻을 수 있습니다.

그러나 다시 말씀드리지만, 이것은 목록을 다시 정렬하는 경우에만 문제가 되므로, 어떤 식으로든 목록을 다시 정렬하지 않을 것이 확실하다면 인덱스를 키로 안전하게 사용할 수 있습니다.

다만, 리스트의 순서를 변경하는 경우(또는 안전을 위해서만), 기존의 일의 식별자가 없는 경우는, 엔티티의 일의 ID 를 생성합니다.

ID를 추가하는 간단한 방법은 목록을 처음 받을목록을 매핑하고 인덱스를 각 항목에 할당하는 것입니다.

const myItemsWithIds = myItems.map((item, index) => { ...item, myId: index });

이렇게 하면 각 항목이 고유한 정적 ID를 얻을 수 있습니다.

tl;dr 이 답을 찾는 새로운 사람을 위한 키를 선택하는 방법

  1. 목록 항목에 고유 ID(또는 다른 고유 속성)가 있는 경우 해당 항목을 키로 사용합니다.

  2. 목록 항목의 속성을 결합하여 고유한 값을 생성할 수 있는 경우 해당 조합을 키로 사용하십시오.

  3. 위의 어느 것도 동작하지 않지만 목록의 순서를 변경하지 않겠다고 약속할 수 있는 경우에는 어레이 인덱스를 키로 사용할 수 있지만 목록을 처음 받거나 작성할 때 자신의 ID를 목록 항목에 추가하는 것이 좋습니다(위 참조).

반응 컴포넌트에 다음 코드를 구현하기만 하면 됩니다.

constructor( props ) {
    super( props );

    this.keyCount = 0;
    this.getKey = this.getKey.bind(this);
}

getKey(){
    return this.keyCount++;
}

전화...리고전전 전전전다다this.getKey()다음과 같은 새로운 키가 필요할 때마다 다음을 수행할 수 있습니다.

key={this.getKey()}

리액트 문서:

키는 안정적이고 예측 가능하며 고유해야 합니다.불안정한 키(Math.random()에 의해 생성된 키 등)는 많은 컴포넌트 인스턴스와 DOM 노드를 불필요하게 재생성하여 자 컴포넌트의 퍼포먼스가 저하되고 상태가 손실될 수 있습니다.

키는 안정적이고 예측 가능하며 고유해야 합니다.불안정한 키(Math.random()에 의해 생성된 키 등)는 많은 컴포넌트 인스턴스와 DOM 노드를 불필요하게 재생성하여 자 컴포넌트의 퍼포먼스가 저하되고 상태가 손실될 수 있습니다.

https://facebook.github.io/react/docs/reconciliation.html

이게 좋은 방법인가요?아무 걱정 없이 사용할 수 있나요?

아니, 아니.

키는 안정적이고 예측 가능하며 고유해야 합니다.불안정한 키(Math.random()에 의해 생성된 키 등)는 많은 컴포넌트 인스턴스와 DOM 노드를 불필요하게 재생성하여 자 컴포넌트의 퍼포먼스가 저하되고 상태가 손실될 수 있습니다.

간단한 예를 들어 설명하겠습니다.

class Input extends React.Component {
  handleChange = (e) =>  this.props.onChange({
    value: e.target.value,
    index: this.props.index
  });
  render() {
    return (
      <input value={this.props.value} onChange={this.handleChange}/>  
    )
  }
};

class TextInputs extends React.Component {
  state = {
    textArray: ['hi,','My','Name','is']
  };
  handleChange = ({value, index}) => {
    const {textArray} = this.state;
    textArray[index] = value;
    this.setState({textArray})
  };
  render(){
  return this.state.textArray.map((txt, i) => <Input onChange={this.handleChange} index={i} value={txt} key={Math.random()}/>)
  // using array's index is not as worse but this will also cause bugs.  
  // return this.state.textArray.map((txt, i) => <Input onChange={this.handleChange} index={i} value={txt} key={i}/>)                 
  };
};

질문한 입력에 여러 문자를 입력할 수 없는 이유는 무엇입니까?

Math.random()을 키프로 하여 여러 텍스트 입력을 매핑하고 있기 때문입니다.문자를 입력할 때마다 onChange 프로펠러에 불이 붙고 부모 컴포넌트의 상태가 변경되어 재렌더가 발생합니다.즉, 각 입력에 대해 Math.random이 다시 호출되어 새로운 키 소품이 생성됩니다.그래서 반응으로 새로운 아이를 렌더링합니다. 컴포넌트를 입력합니다., 문자를 입력할 때마다 키 소품이 변경되었기 때문에 새로운 입력 요소가 생성됩니다.

자세한 내용은 이쪽

키는 안정적이고 예측 가능하며 고유해야 합니다.불안정한 키(에 의해 생성된 키 등)Math.random()의 경우 컴포넌트 가 불필요하게가 저하되거나 자될 수 는 많은 컴포넌트인스턴스와 DOM 노드를 불필요하게 재생성함으로써 퍼포먼스가 저하되고 자 컴포넌트 상태가 상실될 수 있습니다.

각 자식과 자식 내부의 각 요소에 를 추가해야 합니다.

이렇게 하면 React는 최소한의 DOM 변경만 처리할 수 있습니다.

https://reactjs.org/docs/reconciliation.html#recursing-on-children 를 참조해 주세요.여기서는 코드의 예와 함께 최적의 설명을 얻을 수 있습니다.

리모트 API에서 가져온 데이터를 기반으로 타일 목록을 렌더링하는 유스케이스가 있었습니다.예를 들어, 데이터는 다음과 같습니다.

[
  {referrals: 5, reward: 'Reward1'},
  {referrals: 10, reward: 'Reward2'},
  {referrals: 25, reward: 'Reward3'},
  {referrals: 50, reward: 'Reward4'}
]
  • 이 목록은 클라이언트 에서 수정하여 목록의 임의의 엔트리(타일)를 스플라이스/삭제하거나 목록의 끝에 새 엔트리(타일)를 추가할 수 있습니다.

  • 이 목록에 중복 항목이 있을 수 있으므로 목록 항목의 내용을 기반으로 해시/고유 키를 만들 수 없습니다.

만, 이3는 " " " 입니다.4에서 그 를 차지하다33을 제거할 뿐입니다.4의 한 채3이는 바람직하지 않은 동작입니다.

그래서 @josthoff와 @Markus-ipse가 공유한 위의 아이디어를 바탕으로 클라이언트 측 자기계산 카운터를 키로 사용했습니다(https://stackoverflow.com/a/46632553/605027) 참조).

원격 API에서 데이터를 처음 가져올 때 새 키 속성을 추가합니다.

let _tiles = data.tiles.map((v: any) => (
  {...v, key: this.getKey()}
))

그래서 아래와 같이 보인다.

[
  {referrals: 5, reward: 'Reward1', key: 0},
  {referrals: 10, reward: 'Reward2', key: 1},
  {referrals: 25, reward: 'Reward3', key: 2},
  {referrals: 50, reward: 'Reward4', key: 3}
]

를 는, 「타일」에 합니다.this.getKey()이렇게 하면 모든 엔트리(타일)가 고유한 키를 가지며 React는 의도한 대로 동작합니다.

여기서는 임의의 16진수 키 또는 UUID 생성기를 사용할 수 있었지만, 단순성을 위해 자기 증가 카운터를 사용하였습니다.

은 '먹다' 입니다.Math.random()나쁜 생각이긴 하지만, 그건 반쪽만 사실이야. 정도면 쓸 수 Math.random() 데이터를 렌더링하지 않고 처음 수신할 때 작업을 수행할 수 있습니다.

예를 들어 다음과 같습니다.

function SomeComponent() {
  const [items, setItems] = React.useState(() => []);

  React.useEffect(() => {
    fetch('/api/data')
      .then((res) => res.json())
      .then((data) => {
        const itemsWithIds = data.map((item) => {
          return {
            ...item,
            id: Math.random(),
          };
        });

        setItems(itemsWithIds);
      });
  }, []);

  return (
    <div>
      {items.map((item) => (
        <Item key={item.id} item={item} />
      ))}
    </div>
  );
}

의 각 .Math.random()렌더링할 때 이전에 작성한 아이디를 키로 사용합니다.

가장 중요한 것은 각 렌더링에 키를 다시 생성하지 않는 입니다.이러한 설정에서는 API에서 데이터를 수신할 때 키를 한 번만 생성합니다.

이 패턴은 로컬 데이터에서도 거의 모든 상황에서 사용할 수 있습니다.상태 설정기를 호출하기 직전(또는 상태 후크를 초기화하기 전)에는 각 항목에 대해 원하는 ID를 생성할 수 있습니다.

를 사용할 수도 있습니다.crypto.randomUUID()Math.random() 대신 랜덤 번호 대신 UUID를 생성합니다.

컴포넌트 키에 대해 Math.random()을 부여하는 것은 옳지 않다고 생각합니다.왜냐하면 랜덤 번호를 생성했을 때 동일한 번호를 다시 얻을 수 없다는 보장이 없기 때문입니다.컴포넌트를 렌더링하는 동안 동일한 난수가 다시 생성될 가능성이 매우 높기 때문에 이 경우 실패할 수 있습니다.

어떤 사람들은 난수 범위가 더 넓으면 그 숫자가 다시 생성되지 않을 가능성이 매우 낮다고 주장할 것이다.예, 맞습니다만, 코드는 언제든지 경고를 생성할 수 있습니다.

빠른 방법 중 하나는 고유한 새로운 날짜()를 사용하는 것입니다.

언급URL : https://stackoverflow.com/questions/29808636/when-giving-unique-keys-to-components-is-it-okay-to-use-math-random-for-gener

반응형