경고 : 배열 또는 반복기의 각 하위에는 고유 한 "키"소품이 있어야합니다. `ListView`의 렌더링 방법 확인


105

내가 가진 응용 프로그램 내장 ReactNative을 모두 iOS 용 및 안드로이드 ListView. 목록보기를 유효한 데이터 소스로 채울 때 화면 하단에 다음 경고가 인쇄됩니다.

경고 : 배열 또는 반복기의 각 하위에는 고유 한 "키"소품이 있어야합니다. 의 렌더링 방법을 확인하십시오 ListView.

이 경고의 목적은 무엇입니까? 메시지 후 그들은 이 페이지로 연결됩니다 . 여기서 반응 네이티브와는 아무 관련이 없지만 웹 기반 reactjs와 관련된 완전한 다른 것들에 대해 논의합니다.

내 ListView는 다음 문으로 작성됩니다.

render() {
    var store = this.props.store;

    return (

        <ListView
            dataSource={this.state.dataSource}
            renderHeader={this.renderHeader.bind(this)}
            renderRow={this.renderDetailItem.bind(this)}
            renderSeparator={this.renderSeparator.bind(this)}
            style={styles.listView}
            />

    );
}

내 DataSource는 다음과 같이 구성됩니다.

    var detailItems = [];

    detailItems.push( new DetailItem('plain', store.address) );
    detailItems.push( new DetailItem('map', '') );

    if(store.telefon) {
        detailItems.push( new DetailItem('contact', store.telefon, 'Anrufen', 'fontawesome|phone') );
    }
    if(store.email) {
        detailItems.push( new DetailItem('contact', store.email, 'Email', 'fontawesome|envelope') );
    }
    detailItems.push( new DetailItem('moreInfo', '') );

    this.setState({
        dataSource: this.state.dataSource.cloneWithRows(detailItems)
    });

그리고 ListView-Rows는 다음과 같이 렌더링됩니다.

        return (
            <TouchableHighlight underlayColor='#dddddd'>
                <View style={styles.infoRow}>
                    <Icon
                                name={item.icon}
                                size={30}
                                color='gray'
                                style={styles.contactIcon}
                                />
                    <View style={{ flex: 1}}>
                        <Text style={styles.headline}>{item.headline}</Text>
                        <Text style={styles.details}>{item.text}</Text>
                    </View>
                    <View style={styles.separator}/>
                </View>
            </TouchableHighlight>
        );

나에게 완전히 말도 안되는 경고를 제외하고는 모든 것이 정상적으로 작동합니다.

내 "DetailItem"-Class에 키 속성을 추가해도 문제가 해결되지 않았습니다.

이것은 "cloneWithRows"의 결과로 ListView에 실제로 전달되는 것입니다.

_dataBlob: 
I/ReactNativeJS( 1293):    { s1: 
I/ReactNativeJS( 1293):       [ { key: 2,
I/ReactNativeJS( 1293):           type: 'plain',
I/ReactNativeJS( 1293):           text: 'xxxxxxxxxx',
I/ReactNativeJS( 1293):           headline: '',
I/ReactNativeJS( 1293):           icon: '' },
I/ReactNativeJS( 1293):         { key: 3, type: 'map', text: '', headline: '', icon: '' },
I/ReactNativeJS( 1293):         { key: 4,
I/ReactNativeJS( 1293):           type: 'contact',
I/ReactNativeJS( 1293):           text: '(xxxx) yyyyyy',
I/ReactNativeJS( 1293):           headline: 'Anrufen',
I/ReactNativeJS( 1293):           icon: 'fontawesome|phone' },
I/ReactNativeJS( 1293):         { key: 5,
I/ReactNativeJS( 1293):           type: 'contact',
I/ReactNativeJS( 1293):           text: 'xxxxxxxxx@hotmail.com',
I/ReactNativeJS( 1293):           headline: 'Email',
I/ReactNativeJS( 1293):           icon: 'fontawesome|envelope' },
I/ReactNativeJS( 1293):         { key: 6, type: 'moreInfo', text: '', headline: '', icon: '' } ] },

하나의 키에서 알 수 있듯이 각 레코드에는 키 속성이 있습니다. 경고가 여전히 존재합니다.


1
대부분 DetailItem의 경우 키가 필요합니다. 이미 고유 한 키가있는 경우 다른 렌더링 방법 ( renderHeader, renderDetailItem, renderSeparator)을 표시해야합니다 . 그들은 데이터 소스가 어떤 식 으로든 수정 될 때까지 (예를 들어 행이 제거 될 때까지) 정상적으로 작동하고 있으며 React는 고유 식별자가 없을 때 어떻게해야할지 알 수 없습니다.
Pete TNT

"키"란 무엇을 의미합니까? "키"라는 속성?
삭제


그것은 그것을 해결하지 않습니다. 내 데이터 구조에 주요 속성을 추가하고 더 자세한 데이터로 원래 질문을 업데이트했습니다. DataSource에 대한 결과 인 일반 데이터를 나열하면 각 레코드마다 키가 있습니다. 이 경고는 남아 있습니다.
삭제

다른 렌더링 방법 (renderHeader, renderDetailItem, renderSeparator)에서도 올 수 있습니다.
Pete TNT

답변:


95

내가 했어 정확히 잠시 동안 지금 당신과 같은 문제를, 위의 제안 중 일부보고 후, 나는 마침내 문제를 해결했다.

(적어도 어쨌든 나를 위해) renderSeparator 메서드에서 반환하는 구성 요소에 키 ( 'key'라는 소품)를 제공해야했습니다. 내 renderRow 또는 renderSectionHeader에 키를 추가해도 아무 작업도 수행되지 않았지만 renderSeparator에 키를 추가하면 경고가 사라졌습니다.

도움이되기를 바랍니다.


제 경우에는 방금 renderSeparator를 삭제하고 <Separator>를 renderRow 반환 값의 본문으로 옮겼습니다.
boatcoder

에서 똑같이 RN을 만족시키기 위해 각각에 대해 SectionList이름 키가 있는 속성을 명시 적으로 추가해야합니다 item.
LeOn-Han Li

1
이 글을 읽기 전에 JSON 데이터에 문제가 있다고 생각하는 것을 추적하는 데 약 8 시간이 걸렸습니다. 스택 오버플로가있는 경우 : taco : 하나 줄게!
hoekma

77

를 제공해야합니다 .

키 속성이있는 경우 ListView 행에서이 작업을 수행하십시오.

<TouchableHighlight key={item.key} underlayColor='#dddddd'>

그렇지 않은 경우 항목을 키로 추가해보십시오.

<TouchableHighlight key={item} underlayColor='#dddddd'>

1
XD를 복사 할 수 있도록 코드가 있기 때문에이 답변이 더
마음에 듭니다

34

반복 횟수 (i)를 다음 key과 같이 사용할 수도 있습니다 .

render() {
    return (
      <ol>
        {this.props.results.map((result, i) => (
          <li key={i}>{result.text}</li>
        ))}
      </ol>
    );
}

2
어레이가 변경되면 작동하지 않을 수 있습니다. 이 답변은 예를 들어 설명합니다. stackoverflow.com/a/43892905/960857
Chris

21

다음에서 코드 변경 :

render() {
    return (
      <ol>
        {this.props.results.map((result) => (
          <li>{result.text}</li>
        ))}
      </ol>
    );
}

에:

render() {
    return (
      <ol>
        {this.props.results.map((result) => (
          <li key={result.id}>{result.text}</li>
        ))}
      </ol>
    );
}

그런 다음 해결되었습니다.


13

목록의 렌더링 루트 구성 요소에 소품 '키'를 추가합니다.

<ScrollView>
      <List>
          {this.state.nationalities.map((prop, key) => {
             return (
               <ListItem key={key}>
                  <Text>{prop.name}</Text>
               </ListItem>
             );
          })}
      </List>
</ScrollView>

6

이 경고는 목록 항목에 키를 추가하지 않을 때 발생합니다.

키는 React가 어떤 항목이 변경, 추가 또는 제거되었는지 식별하는 데 도움이됩니다. 요소에 안정적인 ID를 제공하려면 배열 내부의 요소에 키를 제공해야합니다.

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

키를 선택하는 가장 좋은 방법은 형제 중에서 목록 항목을 고유하게 식별하는 문자열을 사용하는 것입니다. 대부분의 경우 데이터의 ID를 키로 사용합니다.

const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);

렌더링 된 항목에 대한 안정적인 ID가없는 경우 마지막 수단으로 항목 인덱스를 키로 사용할 수 있습니다.

const todoItems = todos.map((todo, index) =>
  // Only do this if items have no stable IDs
  <li key={index}>
    {todo.text}
  </li>
);

4

renderSeparator Component에 속성을 추가하여 수정했습니다. 코드는 다음과 같습니다.

_renderSeparator(sectionID,rowID){
    return (
        <View style={styles.separatorLine} key={"sectionID_"+sectionID+"_rowID_"+rowID}></View>
    );
}

이 경고의 핵심 단어는 "고유"이며 sectionID + rowID는 ListView에서 고유 한 값을 반환합니다.


4

확인 : key = undef !!!

경고 메시지도 받았습니다.

Each child in a list should have a unique "key" prop.

코드가 완벽하다면

<MyComponent key={someValue} />

someValue가 정의되지 않았습니다 !!! 먼저 확인하십시오. 시간을 절약 할 수 있습니다.


3

renderDetailItem 메서드에 다음 서명 이 있다고 가정합니다 .

(rowData, sectionID, rowID, highlightRow) 

이렇게 해보십시오 ...

<TouchableHighlight key={rowID} underlayColor='#dddddd'>

3

이 문제를 해결하는 데 사용한 특정 코드는 다음과 같습니다.

  renderSeparator(sectionID, rowID, adjacentRowHighlighted) {
    return (
      <View style={styles.separator} key={`${sectionID}-${rowID}`}/>
    )
  }

구분 기호에 대해서도 고유해야하는 키가 필요하기 때문에 특정 코드를 포함합니다. 예를 들어 이것을 상수로 설정하면 비슷한 작업을 수행하면 키 재사용에 대한 또 다른 성가신 오류가 발생합니다. JSX를 모르는 경우 다양한 부분을 실행하기 위해 JS에 대한 콜백을 구성하는 것이 상당히 어려울 수 있습니다.

그리고 ListView에서 분명히 이것을 첨부하십시오.

<ListView
  style={styles.listview}
  dataSource={this.state.dataSource}
  renderRow={this.renderRow.bind(this)}
  renderSeparator={this.renderSeparator.bind(this)}
  renderSectionHeader={this.renderSectionHeader.bind(this)}/>

저를이 길로 안내 해준 coldbuffet과 Nader Dabit에게 감사드립니다.


2

여기 내 이해를 바탕으로합니다. 도움이 되었기를 바랍니다. 뒤에있는 예제로 구성 요소 목록을 렌더링해야합니다. 각 구성 요소의 루트 태그에는 key. 고유 할 필요는 없습니다. 그것은 될 수 없습니다 key=0, key='0'등 그것은 키가 쓸모가 보인다.

render() {
    return [
        (<div key={0}> div 0</div>),
        (<div key={1}> div 2</div>),
        (<table key={2}><tbody><tr><td> table </td></tr></tbody></table>),
        (<form key={3}> form </form>),
    ];
}

0

두 조건이 모두 충족되는 것 같습니다. 아마도 핵심 ( 'contact')이 문제입니다.

 if(store.telefon) {
    detailItems.push( new DetailItem('contact', store.telefon, 'Anrufen', 'fontawesome|phone') );
}
if(store.email) {
    detailItems.push( new DetailItem('contact', store.email, 'Email', 'fontawesome|envelope') );
}

아니요, 연락처는 열쇠가 아닙니다. 그 사이에 "키"라는 부동산을 데이터 구조에 추가하고 질문을 업데이트하여 더 자세한 데이터를 전달했습니다. 아무것도 도움이되지 않습니다. 경고가 남아 있습니다.
삭제


0

이 문제로 나를 괴롭힌 것은 내가 정의한 JSX 요소와 반대로 '실제'또는 DOM HTML 요소처럼 보이는 것에 적용된 키가 필요하다고 생각했다는 것입니다.

물론 React에서 우리는 가상 DOM으로 작업하고 있으므로 우리가 정의한 React JSX 요소는 <MyElement>실제 DOM HTML 요소처럼 보이는 요소만큼 중요합니다 <div>.

말이 돼?


0

제 경우에는 Semantic UI React "Card"뷰를 사용했습니다. 내가 만든 각 카드에 키를 추가하면 경고가 사라졌습니다. 예를 들면 다음과 같습니다.

return (
        <Card fluid key={'message-results-card'}>
          ...
        </Card>
)

-1

<Fade in>반응 애플리케이션에 요소를 사용하는 경우 key={}속성도 추가 하십시오. 그렇지 않으면 콘솔에 오류가 표시됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.