I need a little help in a small issue. In my first screen, I have a flatlist which has some keywords. I want if I click on any keyword, I should be navigated to another screen with the prop of that keyword. I am doing like this inside the flatlist:
<FlatList
data={myRecentSearches}
renderItem={({ item, index }) => (
<TouchableOpacity
onPress={() => props.navigation.navigate("search", { searchValue: `${item.keyword}` })}>
<Text>{item.keyword}</Text>
</TouchableOpacity>
)}
In the next screen, I want the input field should already be initialized with that keyword.
const SearchScreen = (props) => {
const [searchValue, setSearchValue] = useState("");
return (
<View activeOpacity={0.5} style={styles.searchContainer}>
<TextInput
allowFontScaling={false}
value={searchValue} //I want this value to be already initialized/populated with the prop
returnKeyType="search"
autoFocus
/>
</View>
)
}
In your first screen have the SearchScreen like this:
return(
<SearchScreen keyWord={item.keyword}/>
)
And inside SearchScreen:
const SearchScreen = (props) => {
const [searchValue, setSearchValue] = useState(props.keyWord);
return (
<View activeOpacity={0.5} style={styles.searchContainer}>
<TextInput
allowFontScaling={false}
value={searchValue} //I want this value to be already initialized/populated with the prop
returnKeyType="search"
autoFocus
/>
</View>
)
}
Related
I want to use toggle with map function.
I've tried many things, but I returned to the first code. I know what's the problem(I use the map function, but I use only one toggle variable), but I don't know how to fix it.
This is my code.
const [toggle, setToggle] = useState(true);
const toggleFunction = () => {
setToggle(!toggle);
};
{wholeData.map((image)=>{
return(
<TouchableOpacity
key={image.ROWNUM}
onPress={() => navigation.navigate("DetailStore", {
contents: image,
data: wholeData
})}
>
.
.
.
<TouchableOpacity onPress={() => toggleFunction()}>
{toggle ? (
<View style={{marginRight: 11}}>
<AntDesign name="hearto" size={24} color="#C7382A" />
</View>
) : (
<View style={{marginRight:11}}>
<AntDesign name="heart" size={24} color="#C7382A" />
</View>
)}
</TouchableOpacity>
As you've noticed, using a single state for all the toggles won't give you what you want. All you have to do is move your toggle function inside the component you return when you're mapping over your images.
As an unrelated note, you could also simplify your second TouchableOpacity a bit, since the only thing that changes is the icon name.
For example:
// New component
const ListImage = ({ image }) => {
const [toggle, setToggle] = useState(true);
const toggleFunction = () => {
setToggle(!toggle);
};
return (
<TouchableOpacity
key={image.ROWNUM}
onPress={() => navigation.navigate("DetailStore", {
contents: image,
data: wholeData
})}
>
...
<TouchableOpacity onPress={() => toggleFunction()}>
<View style={{ marginRight: 11 }}>
<AntDesign
name={toggle ? "hearto" : "heart"}
size={24}
color="#C7382A"
/>
</View>
</TouchableOpacity>
)
}
// in current component
{wholeData.map((image) => {
return <ListImage image={image} />
})}
const ResolvedPlaces = ({navigation}) => {
return(
<View style={Styles.headerWrapper}>
<TouchableOpacity navigation={navigation} onPress={()=> navigation.navigate("ProfileScreen")} >
<Text style={[Styles.header,{fontWeight:"bold"}]}>Resolved </Text>
<Text style={Styles.header}> places</Text>
</TouchableOpacity>
</View>
)
}
I have created a ResolvedPlaces function and gave a option to route to the profile screen. Also I've destructured the "navigation" in all format. But I continuously got this navgation.navigate as undefined object.
the error message on the terminal
If ResolvedPlaces is not defined as a Screen in a react-native-navigation navigator, then the navigation prop will not be passed automatically to the component ResolvedPlaces.
If ResolvedPlaces is nested inside a Screen that is defined in a Navigator, then you can use the navigation prop directly. This could look as follows.
const SomeScreen = ({navigation}) => {
const ResolvedPlaces = () => {
return(
<View style={Styles.headerWrapper}>
<TouchableOpacity onPress={()=> navigation.navigate("ProfileScreen")} >
<Text style={[Styles.header,{fontWeight:"bold"}]}>Resolved </Text>
<Text style={Styles.header}> places</Text>
</TouchableOpacity>
</View>
)
}
return (
<ResolvedPlaces />
)
}
The component SomeScreen must be defined in a navigator, e.g. a Stack.
If ResolvedPlaces is a component defined in its own file, then pass the navigation object as a prop from the parent that is defined as a screen.
const SomeScreen = ({navigation}) => {
return <ResolvedPlaces navigation={navigation} />
}
If this is not an option than you can still use the useNavigation hook as follows.
const ResolvedPlaces = () => {
const navigation = useNavigation()
return (
<View style={Styles.headerWrapper}>
<TouchableOpacity onPress={()=> navigation.navigate("ProfileScreen")} >
<Text style={[Styles.header,{fontWeight:"bold"}]}>Resolved </Text>
<Text style={Styles.header}> places</Text>
</TouchableOpacity>
</View>
)
}
Remarks: I have removed the navigation prop from the TouchableOpacity since this prop does not exist for this component. The basic react-native-navigation structure is documented here.
const Item = ({ item }) => (
<TouchableOpacity
onPress={() => this.navigation.navigate(
"carProfile",
{item: item}
)}>
<View style={styles.item}>
<Text style={styles.title}>{item.name}</Text>
<Text style={styles.details}>{item.details}</Text>
</View>
</TouchableOpacity>
);
const List = (props,navigation) => {
const renderItem = ({ item }) => {
if (props.searchPhrase === "") {
return <Item item={item} />;
}
if (item.name.toUpperCase().includes(props.searchPhrase.toUpperCase().trim().replace(/\s/g, ""))) {
return <Item item={item} />;
}
if (item.details.toUpperCase().includes(props.searchPhrase.toUpperCase().trim().replace(/\s/g, ""))) {
return <Item item={item} />;
}
};
return (
<SafeAreaView style={styles.list__container}>
<View
onStartShouldSetResponder={() => {
props.setClicked(false);
}}
>
<FlatList
data={props.data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
</View>
</SafeAreaView>
);
};
export default List;
the error is continuing to be there despite me trying to put navigation container in different positions. I want to send the user to the carProfile page, where the data passed in item is reused. This way user can know about the selection they are looking for
Use this way
onPress={() => this.props.navigation.navigate(
"carProfile",
{item: item}
)}
The navigation is inside the props, not as a second argument. Below is a classic example. And also note, you cannot extract navigation prop for child components, it will only work on Main components(Screens).
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
If you want to use navigation inside child components, you can use the navigation hooks.
import { useNavigation } from "#react-navigation/native";
function MyBackButton() {
const navigation = useNavigation();
return (
<Button
title="Back"
onPress={() => {
navigation.goBack();
}}
/>
);
}
I have a FlatList with TouchableOpacity items. When I try to select an item, the list scrolls to top.
This is the Collapsible content;
const setBrandSelected = index => {
var temp = JSON.parse(JSON.stringify(tempFilterOptions));
temp[0].enums[index].selected = !temp[0].enums[index].selected;
setTempFilterOptions(temp);
};
const FilterOptionBrand = () => {
const RenderBrand = ({ item, index }) => {
return (
<TouchableOpacity onPress={setBrandSelected.bind(null, index)}>
{item.selected && (
<View style={[styles.brandImage, styles.selectedBrandImage]}>
<Icon iconName={iconNames.Tick} />
</View>
)}
<FastImage source={{ uri: item.logo }} style={styles.brandImage} resizeMode={FastImage.resizeMode.contain} />
<Text style={styles.brandName}>{item.name}</Text>
</TouchableOpacity>
);
};
const BrandSeparator = () => <View style={styles.brandSeparator} />;
return (
<View style={styles.filterBrandMainContainer}>
<View style={styles.searchBrandContainer}>
<View style={styles.magnifyingGlassWrapper}>
<Icon iconName={iconNames.MagnifyingGlass} />
</View>
<TextInput style={styles.searchBrandInput} placeholder={searchBrandText} />
</View>
<FlatList
horizontal={true}
showsHorizontalScrollIndicator={false}
keyExtractor={(item, index) => String(item.id)}
style={styles.collapsibleContainer}
data={tempFilterOptions[0].enums}
renderItem={RenderBrand}
ItemSeparatorComponent={BrandSeparator}
></FlatList>
</View>
);
};
If you somehow stumble upon this question. The answer is wherever the problem occurs be it Header be it Footer. You should call the component function and not directly just type the function.
const Header = () => <View />
Correct usage;
ListHeaderComponent={Header()}
Incorrect usage;
ListHeaderComponent={Header}
class App extends Component {
constructor() {
super();
this.state = {checked: false}}
onCheck = () => {
const { checked } = this.state;
if(checked == true){this.setState({ checked: false }) }
else {this.setState({ checked: true })}}
render() {
return (
<FlatList
data = {[
{firstName:'User_A',},
{firstName:'User_B',},
{firstName:'User_C',},
{firstName:'User_D',},
{firstName:'User_E',},
]}
renderItem = {({item}) =>
<TouchableOpacity onPress={() => { this.onCheck() }} activeOpacity = {0.5}>
<View style = {{flexDirection : 'row'}}>
<Left>
<Radio selected = {this.state.checked}/>
</Left>
<Card style = {{marginRight : 100, height : 50}}>
<View>
<View>
<Text> {item.firstName} </Text>
</View>
</Card>
</View>
</TouchableOpacity>
}
/>
)
}
}
Using react native i need a flatlist with radio button for selecting each item separately, but when i press an item every item in the list gets selected. How to manage single item selection? Above is my code and sample output
The idea here would be:
To create a separated component to avoid useless re-renders
To store the selected index in the state, and not a boolean, so that the radio button would look like
<Radio selected={this.state.selectedIndex === index}/>, where index is part of the object received by renderItem