0
votes

I'm using react-native-accordion for collapsible listviews. My Code is down bellow. its working but it gives two warnings :

Warning: Failed propType: Invalid prop content supplied to Accordion, expected a single ReactElement. Check the render method of StaticRenderer.

Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of Accordion. It was passed a child from StaticRenderer.

Any idea how to fix it? or any better way to have multiple contents for each header? (Collapsible listviews with childs)

class Courses extends Component {

  constructor(props) {
        super(props);
        this.state = {
          dataSource: new ListView.DataSource({
            rowHasChanged: (row1, row2) => row1 !== row2,
          }),
          loaded: false,
        };
        this.rowPressed = this.rowPressed.bind(this);
    }
  rowPressed(data) {
    console.log('row press');
  }

  fetchData() {
/// fetching data .....
  }

  componentDidMount() {
    this.fetchData();
  }

  render() {
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }

    return (
      <View style={{ flex: 1 }}>
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderRow}
        style={styles.listView}
      />
      </View>
    );
  }

  renderRow(data) {
    var header = (
      <View>
          <View style={styles.rowContainer}>
            <View  style={styles.textContainer}>
              <Text style={styles.title}>{data.nid}</Text>
              <Text style={styles.description} numberOfLines={0}>{data.title}</Text>
            </View>
          </View>
          <View style={styles.separator}/>
        </View>
    );
///////////
    var content = [];
    for(var x=0; x < Object.keys(data.course).length; x++){
      content.push(
        <View style={styles.rowContainer}>
        <TouchableHighlight onPress={() => this.rowPressed(data.course[x].course_id).bind(this)} underlayColor='#e3e0d7'>
        <Text style={styles.child}>{data.course[x].title}</Text>
        </TouchableHighlight>
        </View>
      );
    }
////////////
    return (
      <Accordion
        header={header}
        content={content}
        easing="easeOutCubic"
      />
    );
  }

  renderLoadingView() {
    return (
      <View style={styles.loading}>
        <Text style={styles.loading}>
          Fetching Courses, please wait...
        </Text>
      </View>
    );
  }
}

module.exports = Courses;

Thanks in Advance!


Update : now first error is gone, but it shows all rows in array in one line. i tried adding {'\n'} but it didnt work. any idea how to fix that? or should i use stylesheets?

var content = [];
    for(var x=0; x < Object.keys(data.course).length; x++){
      content.push(

        <TouchableHighlight underlayColor='#e3e0d7'>
        <Text style={styles.child}>{data.course[x].title}</Text>
        </TouchableHighlight>

      );
    }
    var clist = (
      <View style={styles.rowContainer}>
      {content}
      </View>
    );
////////////
    return (
      <Accordion
        header={header}
        content={clist}
        easing="easeOutCubic"
      />
    );

Update 2:

Adding a key to touchablehighlight did fix the second issue. thanks

1
Your renderRow() function forgot to </View> closing tagTrain
@AKADER Thanks for your help, but unfortunately that is not the reason. i didnt forget the closing view tag. if you take a look again you will see <View style={styles.separator}/> has been closed in itself /> anyway i tested what you said but it didnt helpAta Mohammadi
ah sorry didn't see that. I will take another look at it.Train

1 Answers

1
votes

So I looked at an example on facebook for a listview and they have this as an example. To get rid of the second warning try supplying a keyproperty. THis example is supplying it in the _renderSeperator function

 <UIExplorerPage
    title={this.props.navigator ? null : '<ListView>'}
    noSpacer={true}
    noScroll={true}>
    <ListView
      dataSource={this.state.dataSource}
      renderRow={this._renderRow}
      renderScrollComponent={props => <RecyclerViewBackedScrollView {...props} />}
      renderSeparator={this._renderSeperator}
    />
  </UIExplorerPage>

here is the renderSeperator and what it looks like

 _renderSeperator: function(sectionID: number, rowID: number, adjacentRowHighlighted: bool) {
    return (
      <View
        key={`${sectionID}-${rowID}`}
        style={{
          height: adjacentRowHighlighted ? 4 : 1,
          backgroundColor: adjacentRowHighlighted ? '#3B5998' : '#CCCCCC',
        }}
      />
    );
  }
});

you can look at the full example here https://facebook.github.io/react-native/docs/listview.html

and other stackoverflow suggestions here Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `ListView`

As for the first warning it looks like your Accordian has a problem with it's content property. You are giving it an array of Elements when it should only have one element. Try wrapping the array in a single

<View> //<Content /> </View>

because it looks like your Conent inside of

  <Accordion
    header={header}
    content={content}
    easing="easeOutCubic"
  />

looks like this instead

`<Content />
<Content />
<Content />
<Content />
<Content />
//etc... one for every row in the array`

I can't test this out because I don't have my mac so please confirm it.