FlatList keyExtractor not working

import React, { Component } from “react”;
import Icon from “react-native-vector-icons/FontAwesome5”;
import {
WebView,
View,
StyleSheet,
Text,
ActivityIndicator,
Image,
TouchableOpacity,
Modal,
Platform
} from “react-native”;
import { FlatList } from “react-native-gesture-handler”;
import { Linking } from “expo”;

export default class NewsPage extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: [*],
isLoading: true,
modalVisible: false,
modalArticleData: {}
};
}

componentDidMount() {
return fetch(
https://newsapi.org/v2/everything?q=empleos&language=es&apiKey=bc9471b0c90c4d1a8d41860292e59d6b
)
.then(response => response.json())
.then(responseJson => {
this.setState(
{
dataSource: responseJson.articles,
isLoading: false
},
function () { }
);
})
.catch(error => {
console.error(error);
});
}

setModalVisible = articleData => {

if (Platform.OS === "ios") {
  this.setState({
    modalVisible: true,
    modalArticleData: articleData,
  });
} else if (Platform.OS === "android") {
  Linking.openURL(articleData.url);
}
console.log(articleData.id)

};

closeModal = () => {
this.setState({
modalVisible: false,
modalArticleData: {}
});
};

render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, padding: 20 }}>


);
}

return (
  <View
    style={{
      flex: 1,
      alignItems: "center",
      justifyContent: "center"
    }}
  >
    <FlatList
      data={this.state.dataSource}
      keyExtractor={(item, index) => item.id}
      renderItem={({ item }) => (
        <View style={styles.newsListContainer}>
          <Image
            style={styles.newsImage}
            source={{
              uri:
                item.urlToImage != null
                  ? item.urlToImage
                  : "../assets/icon.png"
            }}
          />
          <View style={styles.newsInfo}>
            <Text numberOfLines={2} style={styles.newsTitle}>
              {item.title}
            </Text>
            <Text numberOfLines={3} style={styles.newsDescription}>
              {item.description}
            </Text>
          </View>
          <View>
            <TouchableOpacity
              onPress={() => {
                this.setModalVisible(item);
                // Linking.openURL(item.url);
              }}
            >
              <Text style={styles.newsLink}>Leer</Text>
            </TouchableOpacity>
          </View>
          <View style={styles.divisor}></View>
          <Modal
            animationType="slide"
            transparent={false}
            visible={this.state.modalVisible}
          >
            <View style={styles.newsHeader}>
              <TouchableOpacity
                onPress={() => {
                  this.closeModal();
                }}
              >
                <Icon name="backspace" style={styles.newsClose} />
              </TouchableOpacity>
              {/* <Text>{this.state.modalArticleData.title}</Text> */}
            </View>
            <WebView
              useWebKit={true}
              startInLoadingState={true}
              // useWebKit={true}
              source={{ uri: this.state.modalArticleData.url }}
            />
          </Modal>
        </View>
      )}
      keyExtractor={(item, index) => item.key}
    />
  </View>
);

}
}

NewsPage.navigationOptions = {
headerTitle: “Noticias sobre empleos”
};

const styles = StyleSheet.create({
newsListContainer: {
width: “100%”,
marginVertical: 16,
padding: 16,
flex: 1,
flexDirection: “column”,
alignItems: “center”,
justifyContent: “space-between”
},

newsImage: {
width: “100%”,
height: 150
},

newsInfo: {
padding: 8,
alignSelf: “flex-start”
},

newsLink: {
marginVertical: 8,
alignSelf: “flex-start”,
textTransform: “uppercase”,
padding: 8,
textAlign: “center”,
color: “#F04E22
},

newsTitle: {
fontSize: 18,
color: “#000000”,
marginVertical: 8
},

newsDescription: {
fontSize: 12,
color: “#000000
},

newsHeader: {
flexDirection: “row”,
alignItems: “center”,
marginTop: Platform.OS === “android” ? 0 : 40,
padding: 16
},
newsClose: {
color: “red”,
fontSize: 24
},
divisor: {
width: “100%”,
height: 3,
backgroundColor: “#007bff
}
});

Hi

Please elaborate on what “not working” means?

Can you also please put three backticks on a line by themselves above the code block and another line of three backticks below the code block so that it will be formatted correctly. Like this:

```
code
here
```

Or even better, copy and paste the code into a snack and paste the link to the snack here.

Sample data would also be needed to help you.

I see you’re looking for an id key in an article, but if I look at the articles returned by the query there is no id in the article. There is one in article.source, but it seems often to be null and if not null then it is the same for different articles, so can’t be used for the key.

Hi thanks for your help, I figured somehow to use id.title and it just worked.

1 Like

The reason it probably worked is because the FlatList keyExtractor wants a unique string for each of its items. So when you do something like:

keyExtractor = {item =>  return item.id }

you need to make sure that

  1. item.id is a unique value - it does not repeat anywhere else in the array of items passed to FlatList.
  2. item.id is a string. If it is a number you can do something like:
keyExtractor = {item => return item.id.toString()}

to ensure that it is a string.

1 Like