React Native dropdown api value not selected - javascript

I am using react-native-element-dropdown in react native app. It works fine with default value if set in useState but it's not work with set api response value and not selected in dropdown
import { Dropdown } from "react-native-element-dropdown";
const Profile = ({ navigation, route }) => {
const [country, setCountry] = useState("");
useEffect(() => {
getUserProfile();
}, []);
const getUserProfile = async () => {
return api
.getuserprofile(locale, authValues.user.id, authValues.token)
.then((response) => {
if (response.data.status) {
setCountry(response.data.body.user.country_id);
}
})
.catch((error) => {
//console.log(error);
});
};
return (
<SafeAreaView style={globalStyles.appContainer}>
<View style={globalStyles.inputBox}>
<Text style={globalStyles.inputLabel}>Country of Residence</Text>
<Dropdown
data={CountryData}
search
maxHeight={300}
labelField="value"
valueField="key"
placeholder="Country of Residence"
searchPlaceholder={"Search..."}
value={country}
onChange={(item) => {
setCountry(item.key);
}}
/>
</View>
</SafeAreaView>
);
};
export default Profile;

I've create an example of how to archive it on React native:
import * as React from 'react';
import {useState, useEffect} from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import { Dropdown } from 'react-native-element-dropdown';
import AntDesign from 'react-native-vector-icons/AntDesign';
export default function App() {
const [data, setData] = useState([{
key: 1,
value: 'Australia'
}, {
key: 2,
value: 'New Zeland'
}, {
key: 3,
value: 'The United State'
}]);
const [selectedValue, setSelectedValue] = useState(null);
const [isFocus, setIsFocus] = useState(false);
const getSelected = () => {
fetch('https://api.agify.io/?name=michael').then(res => {
setSelectedValue(3);
}).catch((err) => {
console.log(err);
})
}
useEffect(() => {
getSelected();
}, []);
return (
<View style={styles.container}>
<Dropdown
style={[styles.dropdown, isFocus && { borderColor: 'blue' }]}
data={data}
search
maxHeight={300}
labelField="value"
valueField="key"
placeholder={!isFocus ? 'Select item' : '...'}
searchPlaceholder="Search..."
value={selectedValue}
onFocus={() => setIsFocus(true)}
onBlur={() => setIsFocus(false)}
onChange={item => {
setSelectedValue(item.key);
setIsFocus(false);
}}
renderLeftIcon={() => (
<AntDesign
style={styles.icon}
color={isFocus ? 'blue' : 'black'}
name="Safety"
size={20}
/>
)}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});
and you can check the working example from here

you used item.value insted of item.key
onChange={item => {
setValue(item.value);
setIsFocus(false);
}}

Related

I have a problem with my provider to render different navigator stacks

I am implementing a provider which helps me to have the state of my user in different views, the main function of this provider is to render different one or the other stack navigator depending on whether the variable is full or empty, this in order to be able to generate two groups of screens depending on whether the user is authenticated or not.
Here my code:
View router.tsx:
import { NavigationContainer } from "#react-navigation/native"
import React, { useContext, useEffect, useState, useRef } from "react"
import { UserContext } from "./context/Usuario"
import AuthStack from "./routes/AuthStack"
import GeneralStack from "./routes/GeneralStack"
const Router = () => {
const { me } = useContext(UserContext)
const auth = useRef(false)
useEffect(() => {
return () => {
auth.current = me !== null
console.log("Hola")
}
}, [me])
return (
<NavigationContainer>
{auth.current ? <GeneralStack /> : <AuthStack />}
</NavigationContainer>
)
}
export default Router
Provider user,js:
import React, { useEffect, createContext, useState } from "react"
import AsyncStorage from "#react-native-async-storage/async-storage"
export const UserContext = createContext()
const UserProvider = ({ children }) => {
const [me, setMe] = useState(undefined)
const validStorage = async () => {
try {
const miSesion = await AsyncStorage.getItem("sesion")
console.log(miSesion)
setMe(JSON.parse(miSesion))
} catch (error) {
console.log(`ERROR: ${error.message}`)
}
}
useEffect(() => {
validStorage()
}, [])
return (
<UserContext.Provider value={{ me, setMe }}>
{children}
</UserContext.Provider>
)
}
export default UserProvider
GeneralStack:
import { createNativeStackNavigator } from "#react-navigation/native-stack"
import React from "react"
import TabStack from "./TabStack"
//import TabStack from "./TabStack"
const GeneralScreen = createNativeStackNavigator()
const GeneralStack = () => {
return (
<GeneralScreen.Navigator screenOptions={{ headerShown: false }}>
<GeneralScreen.Screen name="Tabs" component={TabStack} />
</GeneralScreen.Navigator>
)
}
export default GeneralStack
AuthStack:
import { createNativeStackNavigator } from "#react-navigation/native-stack"
import React from "react"
import Login from "../Screens/Login"
import Registro from "../Screens/Registro/Registro"
import SplashScreen from "../SplashScreen"
const AuthScreen = createNativeStackNavigator()
const AuthStack = () => {
return (
<AuthScreen.Navigator
initialRouteName="Splash"
screenOptions={{ headerShown: false }}>
<AuthScreen.Screen name="Login" component={Login} />
<AuthScreen.Screen name="Register" component={Registro} />
<AuthScreen.Screen name="Splash" component={SplashScreen} />
</AuthScreen.Navigator>
)
}
export default AuthStack
Login:
import React, { useState, useContext } from "react"
import {
Image,
ScrollView,
StatusBar,
Text,
TouchableOpacity,
View,
} from "react-native"
import { useNavigate } from "../../Hooks/useNavigate"
import MyTextInput from "../../components/MyTextInput"
import colors from "../../styles/colors"
import { loginStyles } from "../../styles/styles"
import { UserContext } from "../../context/Usuario"
import AsyncStorage from "#react-native-async-storage/async-storage"
export default function Login() {
const [, setIsSession] = useState(false)
const { setMe } = useContext(UserContext)
const navigate = useNavigate()
const [hidePassword, sethidePassword] = React.useState(false)
const [user] = useState({ user: "admin", password: "admin123" })
const [form, setForm] = useState({ user: "", password: "" })
const getStorage = async () => {
if (await AsyncStorage.getItem("sesion")) {
setIsSession(true)
} else {
setIsSession(false)
}
}
const signIn = async () => {
try {
console.log(user)
if (form.user === user.user && form.password === user.password) {
await AsyncStorage.setItem("sesion", JSON.stringify(form))
setMe(form)
setIsSession(true)
}
} catch (error) {
console.error(error)
}
}
const closeSesion = async () => {
await AsyncStorage.removeItem("sesion")
getStorage()
}
return (
<ScrollView contentContainerStyle={[loginStyles.container]}>
<StatusBar backgroundColor={colors.PURPLE} translucent={true} />
<View style={loginStyles.logo}>
<Image
source={require("../../recursos/images/Logo.png")}
style={{ height: 250, width: 250 }}
/>
</View>
<MyTextInput
onChangeText={(text: string) => {
setForm(state => ({ ...state, user: text }))
}}
keyboardType="email-address"
placeholder="E-mail"
/>
<MyTextInput
onChangeText={(text: string) => {
setForm(state => ({ ...state, password: text }))
}}
keyboardType={null}
placeholder="Contraseña"
bolGone={true}
secureTextEntry={hidePassword}
onPress={() => sethidePassword(!hidePassword)}
/>
<View style={loginStyles.btnMain}>
<TouchableOpacity onPress={signIn}>
<Text style={loginStyles.btntxt}>Iniciar Sesión</Text>
</TouchableOpacity>
</View>
<View style={loginStyles.btnTransparent}>
<TouchableOpacity
onPress={() => navigate({ screen: "Register" })}>
<Text
style={[loginStyles.btntxt, { color: colors.PURPLE }]}>
Registrarse
</Text>
</TouchableOpacity>
</View>
<View>
<TouchableOpacity>
<Text
style={[
loginStyles.txtTransparent,
{ textDecorationLine: "none" },
]}>
Olvide mi contraseña
</Text>
</TouchableOpacity>
</View>
</ScrollView>
)
}
Home:
import AsyncStorage from "#react-native-async-storage/async-storage"
import React, { useState } from "react"
import { Image, ScrollView, TouchableOpacity } from "react-native"
import { Calendar } from "react-native-calendars"
import { Text } from "react-native-elements"
import { useNavigate } from "../../Hooks/useNavigate"
import colors from "../../styles/colors"
const Home = () => {
const [showModal, setShowModal] = useState(false)
const [date, setDate] = useState<string>()
const navigate = useNavigate()
const [isSession, setIsSession] = useState(false)
const getStorage = async () => {
const data = await AsyncStorage.getItem("sesion")
console.log(data)
if (data) {
setIsSession(true)
} else {
setIsSession(false)
}
}
const closeSesion = async () => {
await AsyncStorage.removeItem("sesion")
getStorage()
}
return (
<ScrollView>
<TouchableOpacity onPress={() => closeSesion()}>
<Text>Hola porque soy bien molon</Text>
</TouchableOpacity>
<Image
source={require("../../recursos/images/coralio_logo.png")}
style={{
marginTop: 40,
height: 110,
width: "80%",
justifyContent: "center",
alignSelf: "center",
}}
/>
<Calendar
theme={{
selectedDayBackgroundColor: colors.BLACK,
arrowColor: colors.WHITE,
monthTextColor: colors.WHITE,
}}
style={{
backgroundColor: colors.PURPLE,
borderRadius: 10,
elevation: 4,
marginTop: 60,
margin: 10,
height: 400,
}}
onDayPress={day => {
console.log(day.dateString)
setDate(day.dateString)
setShowModal(false)
}}
onMonthChange={() => {}}
initialDate={"2023-01-16"}
minDate={new Date()
.toLocaleDateString("es-US", {
year: "numeric",
month: "2-digit",
day: "numeric",
formatMatcher: "basic",
})
.split("/")
.reverse()
.join("-")}
markedDates={{
day: {
marked: true,
dotColor: colors.WHITE,
selected: true,
selectedColor: colors.PURPLE,
},
}}
//maxDate={"2023-12-31"}
//hideExtraDays={false}
//disableArrowLeft={true}
//disableArrowRight={true}
//hideArrows={true}
//hideDayNames={true}
/>
</ScrollView>
)
}
export default Home
The problem I have is when doing the close session in home, if in login it sends me from the authstack view to generalstack, when I do the close session it doesn't send me back to login, but it does clean the state of the variable from asyncstorage.
Help :(
It looks like you're not clearing the me variable in your context when the user ends the session. I think your closeSesion method should look like this:
const closeSesion = async () => {
setMe(null)
await AsyncStorage.removeItem("sesion")
getStorage()
}

useState array is undefined even though it is initialized as empty array

I'm working in a React Native Expo project with Firebase v9 and I'm getting an error because of my state variabel categories(I think that's the issue).
This component allows the user to add categories to a flatlist, which is seen here:
As it shows i'm already getting an warning which says: '[Unhandled promise rejection: FirebaseError: Function setDoc() called with invalid data. Unsupported field value: undefined (found in field categories in document users/Hk4k6fKrtZZG1BGffFrOTRvuT2h2)]'
And when i add a category i get the error -> Render error: undefined is not an object(evaluating 'iter[symbol.iterator]')
This is the code for my CategoryComponent:
import { StyleSheet, View, FlatList, Alert, Animated} from 'react-native'
import React, { useState, useEffect} from 'react'
import { db, } from '../../firebase/firebase'
import { doc, setDoc, onSnapshot} from 'firebase/firestore';
import firebase from 'firebase/compat/app';
import { Button, Divider, Subheading, Text, Modal, Portal, TextInput } from 'react-native-paper';
import Swipeable from 'react-native-gesture-handler/Swipeable'
import { TouchableOpacity } from 'react-native-gesture-handler';
import { useNavigation } from '#react-navigation/native';
export default function CategoryComponent() {
const containerStyle = {backgroundColor: 'white', padding: 100, margin: 10};
const [textInput, setTextInput] = useState('');
const [visible, setVisible] = useState(false);
const [categories, setCategories] = useState([])
const navigation = useNavigation();
const [dataFetch, setDataFetch] = useState(false);
useEffect(
() =>
onSnapshot(doc(db, "users", `${firebase.auth().currentUser.uid}`), (doc) => {
setCategories(doc.data().categories)
setDataFetch(true)
}
),
console.log(categories),
[]
);
useEffect(() => {
addToFirebase();
}, [categories])
const showModal = () => {
setVisible(true);
}
const hideModal = () => {
setVisible(false);
}
const categoryNavigate = (item) => {
navigation.navigate("Your Organizer tasks", {item});
}
const addCategory = (textInput) => {
setCategories((prevState) => {
return [
{name: textInput, id: Math.floor(Math.random() * 10000) + 1 },
...prevState
];
})
hideModal();
}
const addToFirebase = async() => {
if(dataFetch) {
await setDoc(doc(db, "users", `${firebase.auth().currentUser.uid}`), {
categories: categories
}, {merge: true});
}
};
const deleteItem = (item) => {
setCategories((prevState) => {
return prevState.filter(category => category.id != item.id)
})
}
const DataComponent = (item) => {
const rightSwipe = (progress, dragX) => {
const scale = dragX.interpolate({
inputRange: [-100, 0],
outputRange: [1, 0],
extrapolate: 'clamp'
});
return(
<TouchableOpacity activeOpacity={0.8} onPress={() => deleteItem(item)}>
<View>
<Animated.Text style={[styles.deleteItem, {transform: [{scale}]}]}>Delete</Animated.Text>
</View>
</TouchableOpacity>
)
}
return (
<TouchableOpacity onPress={() => categoryNavigate(item)}>
<Swipeable renderRightActions={rightSwipe}>
<View>
<Text>{item.name}</Text>
</View>
</Swipeable>
</TouchableOpacity>
)
}
return (
<View>
<Subheading>Your categories</Subheading>
<View>
<FlatList
style={styles.flatList}
keyExtractor={(item) => item.id}
data={categories}
renderItem={ ({item}) => (
<DataComponent {...item}/>
)}
/>
</View>
<View>
<Button mode="contained" uppercase={false} onPress={showModal}>
Add a category
</Button>
</View>
<Portal>
<Modal visible={visible} onDismiss={hideModal} contentContainerStyle={containerStyle}>
<Text>Name your category: </Text>
<TextInput placeholder="Enter category name" value={textInput} onChangeText={val => setTextInput(val)}/>
<Button mode="contained" uppercase={false} onPress={() => addCategory(textInput)}>
Add
</Button>
</Modal>
</Portal>
</View>
)
}
I have consol.logged the state variable categories in my useEffect and i don't understand why it shows ''undefined'' when I have initialized it as an empty array, so i would expect to see a empty array in the consol.log for the state variable categories when there is no categories in the flatlist.
If you clearly look there is no such category type key value in the object, so when you perform setCategories(doc.data().categories) it sets the categories value undefined .You can't merge or add a Doc where the field value is undefined.

ReactNative deep cloning state for Flatlist

My FlatList renderItem was re-rendering every item when one of them was changed.
After doing some debugging i deepcloned the state variable which holds the items (+ React.memo), it's working fine now but not sure if it's the optimal solution.
Snack: https://snack.expo.io/-419PhiUl
App.js
import * as React from 'react';
import { View, StyleSheet, FlatList } from 'react-native';
import Constants from 'expo-constants';
import _ from 'lodash';
import Item from './components/Item';
const keyExtractor = item => item.id.toString();
export default function App() {
const [data, setData] = React.useState([
{id: 1, title: 'Post 1', liked: false, user: {name: 'A'}},
{id: 2, title: 'Post 2', liked: false, user: {name: 'B'}},
{id: 3, title: 'Post 3', liked: false, user: {name: 'C'}},
]);
/**
* Like / Unlike the item.
*/
const like = React.useCallback((id) => {
setData(state => {
let clonedState = [...state];
let index = clonedState.findIndex(item => item.id === id);
clonedState[index].liked = ! clonedState[index].liked;
return clonedState;
});
}, []);
/**
* Render items.
*/
const renderItem = React.useCallback(({item}) => (
<Item item={item} onLike={like} />
), []);
const deepClonedData = React.useMemo(() => _.cloneDeep(data), [data]);
return (
<View style={styles.container}>
<FlatList
data={deepClonedData}
renderItem={renderItem}
keyExtractor={keyExtractor}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
}
});
Item.js
import React from 'react';
import {
Text, TouchableOpacity, StyleSheet
} from 'react-native';
function Item({item, onLike}) {
const _onLike = React.useCallback(() => {
onLike(item.id);
}, []);
console.log('rendering', item.title);
return (
<TouchableOpacity onPress={_onLike} style={styles.item}>
<Text>{item.title} : {item.liked ? 'liked' : 'not liked'}</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
item: {
marginVertical: 10,
backgroundColor: 'white',
padding: 15,
borderWidth: 1
}
});
const areEqual = (prevProps, nextProps) => {
return prevProps.item.liked === nextProps.item.liked;
}
export default React.memo(Item, areEqual);

Too many re-renders on search API

I am new to this so I hope this is the right place to get help!
As titled, executing this code is giving me the "Too many re-renders" error on React.
I have tried going through all lines and checking my hooks repeatedly, but nothing seems to work.
I am guessing this is happening due to useEffect, so pasting the code for the relevant components below:
UseResults:
import { useEffect, useState } from 'react';
import yelp from '../api/yelp';
export default () => {
const [results, setResults] = useState([]);
const [errorMessage, setErrorMessage] = useState('');
const searchApi = async () => {
try {
const response = await yelp.get('/search', {
params: {
limit: 50,
term,
location: 'san francisco'
}
});
setResults(response.data.businesses);
} catch (err) {
setErrorMessage('Something went wrong')
}
};
useEffect(() => {
searchApi('pasta');
}, []);
return [searchApi, results, errorMessage];
}
SearchScreen:
import React, { useState } from 'react';
import { Text, StyleSheet } from 'react-native';
import { ScrollView } from 'react-native-gesture-handler';
import ResultsList from '../components/ResultsList';
import SearchBar from '../components/SearchBar';
import useResults from '../hooks/useResults';
const SearchScreen = (navigation) => {
const [term, setTerm] = useState('');
const [searchApi, results, errorMessage] = useResults();
const filterResultsByPrice = (price) => {
return results.filter(result => {
return result.price === price;
});
};
return <>
<SearchBar
term={term}
onTermChange={setTerm}
onTermSubmit={searchApi()}
/>
{errorMessage ? <Text>{errorMessage}</Text> : null}
<Text>We have found {results.length} results</Text>
<ScrollView>
<ResultsList
results={filterResultsByPrice('$')}
title="Cost Effective"
navigation={navigation}
/>
<ResultsList
results={filterResultsByPrice('$$')}
title="Bit Pricier"
navigation={navigation}
/>
<ResultsList
results={filterResultsByPrice('$$$')}
title="Big Spender"
navigation={navigation}
/>
</ScrollView>
</>
};
const styles = StyleSheet.create({});
export default SearchScreen;
ResultsList:
import React from 'react';
import { View, Text, StyleSheet, FlatList } from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import ResultsDetail from './ResultsDetail';
const ResultsList = ({ title, results, navigation }) => {
return (
<View style={styles.container} >
<Text style={styles.title}>{title}</Text>
<FlatList
horizontal
showsHorizontalScrollIndicator={false}
data={results}
keyExtractor={result => result.id}
renderItem={({ item }) => {
return (
<TouchableOpacity onPress={() => navigation.navigate('ResultsShow')}>
<ResultsDetail result={item} />
</TouchableOpacity>
)
}}
/>
</View>
);
};
const styles = StyleSheet.create({
title: {
fontSize: 18,
fontWeight: 'bold',
marginLeft: 15,
marginBottom: 5
},
container: {
marginBottom: 10
}
});
export default ResultsList;
TIA!

Setting params on useEffect and getting the params it on createStackNav in React Navigation 5

I am working on an app where in I need to send or set a particular params of my state in an object.
Here's my object with its respected state:
const [isGlutenFree, setIsGlutenFree] = useState(false);
const [isLactoseFree, setisLactoseFree] = useState(false);
const [isVegan, setIsVegan] = useState(false);
const [isVegetarian, setIsVegetarian] = useState(false);
const saveFilters = () => {
const appliedFilters = {
glutenFree: isGlutenFree,
lactosFree: isLactoseFree,
vegan: isVegan,
isVegetarian: isVegetarian
};
};
These are all sitting on my FiltersScreen.js file. So on my useEffect I tried to use the CommonActions to set the params:
import { CommonActions } from '#react-navigation/native';
useEffect(() => {
props.navigation.dispatch(CommonActions.setParams({ save: saveFilters }));
});
Then inside my Navigator.js file, I tried to receive this and console.log this on the screen to see that it has the data I need:
<FilterNav.Screen
name="Filters"
component={FiltersScreen}
options={({ route }) => ({
title: 'Filters',
headerLeft: () => (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title='Menu'
iconName='ios-menu'
onPress={() => {
navigation.toggleDrawer();
}}
/>
</HeaderButtons>
),
headerRight: () => (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title='Save'
iconName='ios-save'
onPress={() => {
// CONSOLE LOG THE PARAMS SET >>
console.log(route.params.save);
}}
/>
</HeaderButtons>
)
})}
/>
</FilterNav.Navigator>
To be specific on this part:
headerRight: () => (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title='Save'
iconName='ios-save'
onPress={() => {
// CONSOLE LOG THE PARAMS SET >>
console.log(route.params.save);
}}
/>
</HeaderButtons>
)
But this doesn't work and doesn't return anything. Also it freezes all of my Switches.
Here's the complete code for FiltersScreen.js:
import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, Switch, Platform } from 'react-native';
import { CommonActions } from '#react-navigation/native';
import Colors from '../constants/colors';
const FiltersSwitch = props => {
return(
<View style={styles.filterContainer}>
<Text>{ props.label }</Text>
<Switch
trackColor={{ true: Colors.primaryColor }}
thumbColor={Platform.OS === 'android' ? Colors.primaryColor : ''}
value={props.state}
onValueChange={props.onChange} />
</View>
);
};
const FiltersScreen = props => {
const [isGlutenFree, setIsGlutenFree] = useState(false);
const [isLactoseFree, setisLactoseFree] = useState(false);
const [isVegan, setIsVegan] = useState(false);
const [isVegetarian, setIsVegetarian] = useState(false);
// We will give this a connection with the
// MealsNavigator in order to trigger this
// function via useEffect
const saveFilters = () => {
const appliedFilters = {
glutenFree: isGlutenFree,
lactosFree: isLactoseFree,
vegan: isVegan,
isVegetarian: isVegetarian
};
};
useEffect(() => {
props.navigation.dispatch(CommonActions.setParams({ save: saveFilters }));
});
return (
<View style={styles.screen}>
<Text style={styles.title}>Available Filters / Restrictions</Text>
<FiltersSwitch
label="Glutten Free"
state={isGlutenFree}
onChange={newValue => setIsGlutenFree(newValue)} />
<FiltersSwitch
label="Lactose Free"
state={isLactoseFree}
onChange={newValue => setisLactoseFree(newValue)} />
<FiltersSwitch
label="Vegan"
state={isVegan}
onChange={newValue => setIsVegan(newValue)} />
<FiltersSwitch
label="Vegetarian"
state={isVegetarian}
onChange={newValue => setIsVegetarian(newValue)} />
</View>
);
}
const styles = StyleSheet.create({
screen: {
flex: 1,
alignItems: 'center'
},
title: {
fontFamily: 'poppins-bold',
fontSize: 22,
margin: 20,
textAlign: 'center'
},
filterContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
width: '80%',
marginVertical: 15
}
});
export default FiltersScreen;
And here's the complete code for the navigation.js file:
const FilterNav = createStackNavigator();
const FiltersNavigator = () => {
return (
<FilterNav.Navigator
mode="modal"
screenOptions={{
headerStyle: {
backgroundColor: Colors.primaryColor,
},
headerTintColor: '#fff',
headerTitleStyle: {
fontSize: 17
}
}}
>
<FilterNav.Screen
name="Filters"
component={FiltersScreen}
options={({ route }) => ({
title: 'Filters',
headerLeft: () => (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title='Menu'
iconName='ios-menu'
onPress={() => {
navigation.toggleDrawer();
}}
/>
</HeaderButtons>
),
headerRight: () => (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title='Save'
iconName='ios-save'
onPress={() => {
console.log(route.params.save);
}}
/>
</HeaderButtons>
)
})}
/>
</FilterNav.Navigator>
);
};
Please help how to solve this been stuck for a couple of time. I am using React Navigation 5.
I guess the "freeze" problem is that your useEffect is executing in every screen render, since it has no dependency array (read Tip: Optimizing Performance by Skipping Effects).
Your code should look something like this:
// useCallback, so it doesn't create a new saveFilters function in every render
const saveFilters = useCallback(() => {
const appliedFilters = {
glutenFree: isGlutenFree,
lactosFree: isLactoseFree,
vegan: isVegan,
isVegetarian: isVegetarian
};
}, [isGlutenFree, isLactoseFree, isVegan, isVegetarian]); // This function depends on those variables.
useEffect(() => {
props.navigation.dispatch(CommonActions.setParams({ save: saveFilters }));
}, [saveFilters]); // It should change the parameterized function if it changes

Categories

Resources