I have a React Native web app with a card item that shows category items. For example, parrots can have multiple categories, like: parrots1, parrots2, parrots3. If a user clicks on parrots1, this category can also have multiple subcategories, such as: parrots1.1, parrots1.2, etc. It’s a one-to-many relationship.
A user can click on a card item and be navigated to the next card items with the categories. For example, category item 1 has subcategories: 1, 3, 5. This works fine.
Now, I want to implement a back button so that the user can return to the previous card items. I implemented a previous state reference using the useEffect hook, like this:
useEffect(() => {
if (previousStateRef.current) {
console.log("Previous state:", previousStateRef.current);
}
// Update ref to current state after render
previousStateRef.current = subCatgoryList;
}, [subCatgoryList]);
I can retrieve the previous state items, but I need to use this previous state with a button so that the user can see the previous card items.
I implemented a function to update the previous state reference, like this:
const updatePreviousStateRef = (currentState) => {
if (previousStateRef.current) {
console.log("Previous state:", previousStateRef.current);
}
previousStateRef.current = currentState;
};
And I created a button for using that function:
<Button icon="arrow-left" mode="contained" onPress={updatePreviousStateRef}>
Back to Card
</Button>
But this does not work. If a user press on the button. This will be returned:
Previous state: SyntheticBaseEvent {_reactName: 'onClick', _targetInst: null, type: 'click', nativeEvent: PointerEvent, target: div.css-text-146c3p1.r-maxWidth-dnmrzs.r-overflow-1udh08x.r-textOverflow-1udbk01.r-whiteSpace-3s2u2…, …}
So for brevity, this is the whole code:
import { ActivityIndicator, Pressable, StyleSheet, View } from "react-native";
import { Button, MD2Colors, Searchbar } from "react-native-paper";
import {
CategoryList,
LoadingContainer,
} from "/src/components/general/view-flatlist-card";
import React, { useContext, useEffect, useRef, useState } from "react";
import { AccordionCategoryItemsContext } from "../../../services/accordian-category-items.context";
import { AccordionItemsContext } from "../../../services/accordion-items.context";
import { AnimalDetailToggle } from "../../../components/general/animal-detail-toggle-view";
import { AntDesign } from "@expo/vector-icons";
import { ButtonDetail } from "./animal-detail.screen";
import { SafeArea } from "../../../components/utility/safe-area.component";
import { SearchAnimalContext } from "../../../services/search-animal.context";
import { Spacer } from "../../../components/spacer/spacer.component";
import { SubCategoryInfoCard } from "../components/subcategory-info-card.component";
import { ToggleContext } from "../../../services/toggle.context";
import { fetchSubCategoryData } from "../../../services/category/category.service";
import { useNavigationState } from "@react-navigation/native";
export const SubCategoryScreen = ({ route, navigation }) => {
const [subCatgoryList, setSubCategoryList] = useState([]);
const [isLoading, setLoading] = useState(true);
const { performSearch, results, setInput, input } =
useContext(SearchAnimalContext);
const { toggle, showAccordion } = useContext(ToggleContext);
const [toggleIcon, setToggleIcon] = useState(true);
const { accordionCategoryItems } = useContext(AccordionCategoryItemsContext);
const { accordionItems } = useContext(AccordionItemsContext);
const [isSearchbarFocused, setSearchbarFocused] = useState(false);
const previousStateRef = useRef();
useEffect(() => {
fetchSubCategoryData(route.params.subcategories).then((data) => {
setSubCategoryList(
data.animals.length > 0 ? data.animals : data.subcategories
);
setLoading(false);
});
}, [route]);
useEffect(() => {
if (previousStateRef.current) {
console.log("Previous state:", previousStateRef.current);
}
// Update ref to current state after render
previousStateRef.current = subCatgoryList;
}, [subCatgoryList]);
const handleSearchChange = (text) => {
setInput(text);
if (text.length === 0) {
performSearch(""); // Clear results when the input is empty
navigation.navigate("dieren");
} else {
performSearch(text);
}
};
const handleToggle = (itemId) => {
toggle(itemId);
setToggleIcon(!toggleIcon);
};
const updatePreviousStateRef = (currentState) => {
if (previousStateRef.current) {
console.log("Previous state:", previousStateRef.current);
}
previousStateRef.current = currentState;
};
return (
<SafeArea>
<View style={styles.headerContainer}>
<Button icon="arrow-left" mode="contained" onPress={updatePreviousStateRef}>
Back to Card
</Button>
</View>
{isLoading && (
<LoadingContainer>
<ActivityIndicator animating={true} color={MD2Colors.green200} />
</LoadingContainer>
)}
<Searchbar
placeholder="Zoek een dier"
value={input}
onFocus={() => setSearchbarFocused(true)}
onChangeText={handleSearchChange}
onBlur={() => setSearchbarFocused(false)}
style={styles.searchbar}
/>
{results.length > 0 ? (
<AnimalDetailToggle />
) : (
<CategoryList
data={subCatgoryList.filter((item) =>
item.name.toLowerCase().includes(input.toLowerCase())
)}
renderItem={({ item }) => (
<>
{console.log(item.id)}
<Pressable
onPress={() =>
navigation.navigate("groepen", { subcategories: item.id })
}
disabled={isLoading || (!item.animals && !item.subcategories)}
>
<Spacer>
<SubCategoryInfoCard subcategories={item} />
</Spacer>
</Pressable>
<View>
{(item.subcategories || !item.animals) && (
<ButtonDetail onPress={() => handleToggle(item.id)}>
<AntDesign
name={toggleIcon ? "downcircle" : "upcircle"}
size={19}
color="green"
/>
</ButtonDetail>
)}
</View>
{item.subcategories &&
item.animals &&
showAccordion.includes(item.id) &&
accordionCategoryItems(item)}
{(!item.animals || !item.subcategories) &&
showAccordion.includes(item.id) &&
accordionItems(item)}
</>
)}
keyExtractor={(item) => item.id}
/>
)}
</SafeArea>
);
};
const styles = StyleSheet.create({
searchbar: {
marginBottom: 10,
borderRadius: 0,
},
});
Question: how to navigate with the back button to the previous card items?