cmcodes
cmcodes

Reputation: 1866

How to pass an array from a parent component to child component using props in React Native?

I want to paas "subjects" array from SubjectsScreen to MarkAttendanceScreen and display the array items as a FlatList.

Parent Component

export default class SubjectsScreen extends Component {
    state = {
      subjects: ["A", "B"]
    };

    render() {
      return (
          ...
          <MarkAttendanceScreen subjectsArray={this.state.subjects} />
      );
    }
}

Child Component

export default class MarkAttendanceScreen extends Component {

    constructor(props) {
      super(props);
      this.state = {
        subjects: []
      };
    }

    componentDidMount() {
      this.setState({ subjects: this.props.subjectsArray });
    }

    render() {
      return (   
        <FlatList>
            { this.props.subjects.map((item, key)=>(
                <Text key={key}> { item } </Text>)
            )}
        </FlatList>
      );
    }
}

Upvotes: 1

Views: 710

Answers (4)

cmcodes
cmcodes

Reputation: 1866

Using props was giving error when using FlatList with map. Works fine when extracting value directly from AsyncStorage.

export default class MarkAttendanceScreen extends Component {

  state = {
    subjects: [],
    text: ""
  }

  componentDidMount() {
    Subjects.all(subjects => this.setState({ subjects: subjects || [] }));
  }

  render() {
    return (
      <View>
        <FlatList
          data={ this.state.subjects}
          renderItem={({item}) => {
            return (
              <View>
                  <Text> { item.text } </Text>
              </View>
            )
          }}
          keyExtractor={ (item, index) => index.toString()}
        />
      </View>
    );
  }
}

let Subjects = {
  convertToArrayOfObject(subjects, callback) {
    return callback(
    subjects ? subjects.split("\n").map((subject, i) => ({ key: i, text: subject })) : []
    );
  },
  convertToStringWithSeparators(subjects) {
    return subjects.map(subject => subject.text).join("\n");
  },
  all(callback) {
    return AsyncStorage.getItem("SUBJECTS", (err, subjects) =>
    this.convertToArrayOfObject(subjects, callback)
    );
  },
};

Upvotes: 1

cschultz1272
cschultz1272

Reputation: 130

D. Smith is correct, you need to change that line to this.state.subjects.map But could also just remove the state variable from the Child Component and use the array directly from props.

export default class MarkAttendanceScreen extends Component {

  constructor(props) {
    super(props);
  }

  render() {
    return (   
      <FlatList>
          { this.props.subjectsArray.map((item, key)=>(
              <Text key={key}> { item } </Text>)
          )}
      </FlatList>
    );
  }
}

Update:

Flatlists need to be defined like this:

<FlatList
    data={ this.props.subjectsArray }
    renderItem={({item}) => {
        return (
             <Text> { item } </Text>)
        )
    }}  
   keyExtractor={(item, index) => index}
/>

or you can use it the way you have it and remove the flatlist like:

return this.props.subjectsArray.map((item, key)=>(
        <Text key={key}> { item } </Text>)
       )}

Upvotes: 0

Zohaib Ijaz
Zohaib Ijaz

Reputation: 22875

You must use the same key name that you used while passing down data to child component e.g. in your case you used key subjectsArray here and You don't need to store this first in state and then use unless you want to update it later.

<MarkAttendanceScreen subjectsArray={this.state.subjects} />

So in your child component, it will be

<FlatList>
   {this.props.subjectsArray.map((item, key)=>(
       <Text key={key}> { item } </Text>
   ))}
</FlatList>

Upvotes: 0

D. Smith
D. Smith

Reputation: 749

this.props.subjects does not exist, but you did set the state in componentDidMount. In the FlatList use this.state.subject.map.

render() {
  return (   
    <FlatList>
        { this.state.subjects.map((item, key)=>(
             // ^here
            <Text key={key}> { item } </Text>)
        )}
    </FlatList>
  );
}

Upvotes: 0

Related Questions