Onglets de catégorie native React - chaque onglet affiche une catégorie différente

Nov 29 2020

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

KenLee Nov 29 2020 at 13:20

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.

RajshekharYadav Nov 29 2020 at 14:07

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.

SaachiTech Nov 30 2020 at 07:31

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 pageparamètre donné .