Onglets de catégorie native React - chaque onglet affiche une catégorie différente
J'essaie actuellement de mettre en œuvre un écran de navigation, où les utilisateurs peuvent choisir une catégorie spécifique à partir d'un ScrollView qui rend les messages liés à cette catégorie.
Mon API obtient toutes les données de publication du backend et pour chaque publication, j'ai un paramètre d'appel categoryId.
Ce que j'essaie de faire, par exemple, si l'une de mes catégories est le sport. lorsque l'utilisateur sélectionne l'onglet sports, une liste plate avec tous les articles sur les sports doit être rendue.
Avec cette implémentation actuelle, j'ai mes onglets de catégorie et lorsque je sélectionne l'un des onglets, tous les messages sont rendus et non les messages de cette catégorie spécifique.
Voici mon code:
function SearchScreen({ navigation }) {
const [posts, setPosts] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const loadPosts = async () => {
setLoading(true);
const response = await postsApi.getPosts(page);
setLoading(false);
if (!response.ok) return setError(true);
setError(false);
setPosts(response.data);
};
const[page,setPage]=useState(0);
useEffect(() => {
loadPosts();
}, []);
const categories = [
{
label: "Sports",
id: 1,
},
{
label: "Fashion",
id: 2,
},
{
label: "News",
id: 3,
},
];
const[label,setLabel]=useState('Sports')
const[dataList,setDataList]=useState(posts)
const setLabelFilter=label=>{
setLabel(label)
}
return (
<>
<ActivityIndicator visible={loading} />
<Screen style={styles.screen}>
{error && (
<>
<View style={styles.error}>
<AppText>Could not retrieve posts from server.</AppText>
<AppButton title="Retry" onPress={loadPosts} />
</View>
</>
)}
<ScrollView
horizontal
style={{flexDirection:"row",
alignContent:"center",
width:Dimensions.get('window').width/1.05,
marginBottom:20,
}}
showsHorizontalScrollIndicator={false}
>
{categories.map(e=>(
<TouchableOpacity
style={[
{paddingHorizontal:10,paddingBottom:10},
label===e.label &&
{borderBottomWidth:3,
borderBottomColor:colors.primary,
borderRadius:2,
}
]}
onPress={()=>setLabelFilter(e.label)}
>
<AppText style={[{fontWeight:"500",color:colors.medium},label===e.label &&
{color:colors.primary,fontWeight:"700"}]}>{e.label}</AppText>
</TouchableOpacity>
))}
</ScrollView>
<FlatList
data={posts} // to have all the data
keyExtractor={(post) => post.id.toString()}
renderItem={({ item,index }) => (
<Card
title={item.title}
subTitle={item.subTitle}
onPress={() => navigation.navigate(routes.POST_DETAILS, {post:item,index})}
/>
)}
/>
</Screen>
</>
);
}
Quand je fais console.log (posts), voici à quoi ressemble ma réponse:
Object {
"Category": Object {
"id": 1,
"name": "Sports",
},
"categoryId": 3,
"createdAt": "2020-11-18T13:43:19.616Z",
"deletedAt": null,
"id": 506,
"subtTitle": "test",
"title": "test",
"updatedAt": "2020-11-23T06:57:44.150Z",
"userId": 1,
},
J'ai pensé à changer mon appel API pour obtenir la catégorie par son identifiant, puis inclure tous les messages pour chaque catégorie spécifique, mais cela n'a pas fonctionné, alors je suis allé avec l'appel API pour obtenir tous les messages.
Mettre à jour
const[label,setLabel]=useState('Sports')
const setLabelFilter=label=>{
setLabel(label)
}
const [currentCategoryId, setCurrentCategoryId] = useState()
const toggleBrands = (categoryId) => {
setCurrentCategoryId(categoryId)
setLabel(label)
};
return(
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
>
{categories.map(e=>(
<TouchableOpacity
key={e.id}
onPress={()=>{toggleBrands(e.id),
setLabelFilter(e.label)}}
selected={e.id === currentCategoryId}
>
<AppText>{e.label}</AppText>
</TouchableOpacity>
))}
</ScrollView>
<FlatList
data={currentCategoryId ?
posts.filter(post=>post.categoryId===currentCategoryId
):posts}
J'ai essayé le code suivant, quelqu'un peut-il me dire s'il est correct ou non?
Réponses
Pour vous donner un exemple, disons que vous cliquerez d'abord sur un élément dans une Flatlist (affichant toutes les catégories) sur l'écran A, puis le système naviguera vers l'écran B (avec Flatlist montrant les éléments de la catégorie sélectionnée uniquement)
La méthode normale consiste à afficher dynamiquement uniquement les données de la catégorie sélectionnée, par exemple par un script php (pour cet exemple, il s'agit de sjson.php)
Pour l'écran A, ce sera comme ceci:
Écran Une fonction GetFlatListItem:
GetFlatListItem (fruit_name) {
this.props.navigation.navigate('ScreenB', {unitserial: fruit_name})
}
Screen Une Flatlist peut être comme ceci:
data={ this.state.dataSource }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item}) =>
<View style={{flex: 1, flexDirection: 'row', justifyContent:'flex-start'}}>
<Text onPress={this.GetFlatListItem.bind(this, item.serial)} >
{item.ok}</Text>
</View>
Pour l'écran B, ce sera comme ceci:
const enstring='https://www.test.com/sjson.php?serial=' + this.props.route.params.unitserial ;
return fetch(enstring)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
et la Flatlist peut être comme:
<FlatList
data={ this.state.dataSource }
>
Veuillez noter que vous devrez modifier vos codes en fonction de vos besoins. Ce qui précède n'est qu'un exemple.
Définissez d'abord les états:
const [apiRespPonse, setApiRespone] = useState("");
const [selectedTabData, setSelectedPost] = useState("");
const [category, setCategory] = useState("Sports");
Dans votre appel d'API, définissez The Response:
const fetchAllPost = () => {
setApiRespone([]);
const newArr = apiRespPonse.filter(obj => obj.label===category);
setSelectedPost(newArr)
};
Pour votre option de rendu, utilisez le filtre pour le tableau pour obtenir les données de l'onglet sélectionné:
return (
<View style={styles.app}>
<View style={styles.header}>
<View style={{ flexDirection: "row" }}>
{categories.map((item, index) => {
return <Text onPress={()=>{
setCategory(categories[index])
const newArr = apiRespPonse.filter(obj => obj.label===category);
setSelectedPost(newArr)
}} style={styles.title}>{item.label}</Text>;
})}
</View>
</View>
<FlatList
data={selectedTabData}/>
</View>
);
};
Peut-être que cela peut aider.
Si je comprends bien, vous souhaitez simplement actualiser le contenu de la liste plate avec la catégorie sélectionnée. Je pense que le code que vous avez avant les mises à jour fait tout ce dont vous avez besoin avec de petites mises à jour. Voici la partie du code qu'il vous suffit de mettre à jour
{categories.map((e,index)=>(
<TouchableOpacity
...
style={[
...
index===page && {
borderBottomWidth:3,
borderBottomColor:colors.primary,
borderRadius:2,
}]
onPress={()=>{setPage(index)}}
>
...
</TouchableOpacity>
)}
Assurez-vous que postsApi.getPosts(page);
renvoie des données correctes en fonction du page
paramètre donné .