I'm trying to implement a select dropdown menu in a React Native application using npm's react-native-dropdown-picker package.
I successful did it in one of the application's views/screens and tried to replicate by the same way but the dropdown menu is not rendering the options.
Checking the redux's store is possible to see the data that should be rendered, and in other view it does render. The data is the same for both screens such as the picker component.
return (
<>
<DefaultHeader navigation={navigation} />
<Container>
<ScrollView
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={() => setRefreshing(true)}
/>
}>
<SalesAccountFilter /> // <-- Dropdown is rendered but dont render options
{isLoading === true ? (
<View style={{marginTop: '50%'}}>
<Spinner color="#054785" />
</View>
) : (
<Content>
...some content
</Content>
)}
</ScrollView>
</Container>
</>
);
In the other screen that the dropdown is implemented in the exactly same way it is working fine. There is no error about it on the console. In the following snippet is the implementation of "SalesAccountFilter".
const styles = StyleSheet.create({
picker: {
maxWidth: 320,
minWidth: 320,
color: 'black',
zIndex: 1000,
},
pickerPlaceholder: {
color: '#bfc6ea',
},
});
...
return (
<DropDownPicker
style={styles.picker}
items={[...accounts]}
defaultValue={null}
placeholder="Select an account . . ."
placeholderStyle={styles.pickerPlaceholder}
containerStyle={{height: 40, width: 320}}
labelStyle={{
fontSize: 14,
textAlign: 'left',
color: '#000',
}}
itemStyle={{justifyContent: 'flex-start'}}
dropDownStyle={{backgroundColor: '#fafafa'}}
onChangeItem={handleSelected}
searchable={true}
searchablePlaceholder="Search account"
searchableError={() => <Text>Not found</Text>}
activeLabelStyle={{color: 'blue'}}
/>
);
**Versions:**
Ubuntu 20.04lts;
Node v15.5.0;
React Native Picker 1.9.8;
React 17.0.1;
Nativebase 2.15.0;
React Native 0.63.4;
Emulator: Pixel 4 (latest build);
Related
for some reason a ScrollView in one of my components isn't working despite working in every other component I've implemented it in. Attempting to implement solutions to similar problems seems to just make the content I want displayed disappear.
I'm expecting to have a scrollable list of sample restaurant dishes. I created some dummy data to pass in for now but noticed it didn't scroll after reaching the end of the phone screen.
const testFoods = [
{
title: "test",
description: "Lorem Ipsum",
price: "$7.77",
image: "dummyLink",
},
// Same as above but 4 more times, didn't want to clog up the description
];
export default function MenuItems() {
return (
<ScrollView showsVerticalScrollIndicator={false}>
{testFoods.map((food, index) => (
<View key={index}>
<View style={styles.menuItemStyle}>
<FoodDetails food={food} />
<FoodImage food={food} />
</View>
</View>
))}
</ScrollView>
);
}
const FoodDetails = (props) => (
<View style={{ width: 240, justifyContent: "space-evenly" }}>
<Text style={styles.titleStyle}>{props.food.title}</Text>
<Text>{props.food.description}</Text>
<Text>{props.food.price}</Text>
</View>
);
const FoodImage = (props) => (
<View>
<Image
source={{ uri: props.food.image }}
style={{
width: 100,
height: 100,
borderRadius: 8,
}}
/>
</View>
);
const styles = StyleSheet.create({
menuItemStyle: {
flexDirection: "row",
justifyContent: "space-between",
margin: 20,
},
titleStyle: {
fontSize: 19,
fontWeight: "600",
},
});
The result is like so
Result with code above
The Header component with the sample restaurant image is a separate component by the way.
I have more data that can't be seen as for whatever reason the screen refuses to scroll. I'm using my actual phone for the tests but the result is the same when I use an emulator, scrolling doesn't work. After looking online I thought I would try adding a parent View with flex: 1 and a flexGrow: 1 to contentContainerStyle inside the ScrollView like so.
export default function MenuItems() {
return (
<View style={{ flex: 1 }}>
<ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={{ flexGrow: 1 }}
>
{testFoods.map((food, index) => (
<View key={index} style={styles.menuItemStyle}>
<FoodDetails food={food} />
<FoodImage food={food} />
</View>
))}
</ScrollView>
</View>
);
}
But that only resulted in the content disappearing. Reloading the app didn't change anything either Result after trying above code
Attempting to use a FlatList had the same result. I've also read that having percentage based styling values on height for any of the children components can make the scrolling stop working but all my components don't utilize such. Oddly enough when I change the styling on the outer view to height: 400, I'm able to get the scrolling to work but this is very sloppy and will likely only work on phone screens similar to mine. I know the ScrollView component is working fine, as when I add "horizontal" to it the scrolling works just fine and I'm able to scroll to the last item in the dataset. Obviously all the content is horizontal now though. After adding horizontal too ScrollView, scrolling works fine horizontally
Any ideas? Could it be some part of my styling I'm not noticing? I'm unable to test this on IOS so I'm not sure if it's an Android specific problem, would be strange though as scrolling worked fine in my other components.
Here's also the Header component code just in case it could be anything in there, although It shouldn't be.
const testImage =
"https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Restaurant_N%C3%A4sinneula.jpg/800px-Restaurant_N%C3%A4sinneula.jpg";
const testTitle = "Sample Restaurant";
const testDescription = "Thai · Comfort · $$ · 🎫 · 4 ⭐ (217+)";
export default function About() {
return (
<View>
<RestaurantImage image={testImage} />
<RestaurantTitle title={testTitle} />
<RestaurantDescription description={testDescription} />
</View>
);
}
const RestaurantImage = (props) => (
<Image source={{ uri: props.image }} style={{ width: "100%", height: 180 }} />
);
const RestaurantTitle = (props) => (
<Text
style={{
fontSize: 29,
fontWeight: "600",
marginTop: 10,
marginHorizontal: 15,
}}
>
{props.title}
</Text>
);
const RestaurantDescription = (props) => (
<Text
style={{
marginTop: 10,
marginHorizontal: 15,
fontWeight: "400",
fontSize: 15.5,
}}
>
{props.description}
</Text>
);
Wrap your card with TouchableOpacity.
<TouchableOpacity activeOpacity={0} key={index} style={styles.menuItemStyle}>
<FoodDetails food={food} />
<FoodImage food={food} />
</TouchableOpacity>
I hope this thing will work.
I keep getting this error saying "ERROR Warning: React has detected a change in the order of Hooks called by MainMenuScreen. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks". Really confused don't know why am getting this error if someone can please explain or show an example it would greatly be appreciated. Many thanks for considering my request.
Here is an image of the code.
function MainMenuScreen({ navigation, route, props }) {
const globalContext = useContext(Context)
const { setIsLoggedIn, appSettings, domain, userObj, setUserObj, setToken, address, setAddress } = globalContext;
const [selecedTab, setSelectedTab] = React.useState(tabs[0]);
return (
<View style={styles.container}>
<LinearGradient colors={['gold', '#FF7F50', '#FF7F50']} style={StyleSheet.absoluteFill}>
<FlatList
data={tabs}
horizontal
showsHorizontalScrollIndicator={false}
style={{ flexGrow: 0 }}
keyExtractor={(item, index) => `${item}-${index}`}
renderItem={({ item: tab }) => {
return (
<TouchableOpacity onPress={() => setSelectedTab(tab)}>
<View style={[styles.pill,
{
backgroundColor: selecedTab === tab ? 'gold' : 'transparent',
},
]}>
<Text style={[styles.pillText, { color: selecedTab === tab ? 'white' : 'black' }]}>{tab}</Text>
</View>
</TouchableOpacity>
)
}}
/>
<FlatList
data={popularFood}
keyExtractor={item => item.key}
renderItem={({ item }) => {
return (
<View style={{ flexDirection: 'row' }}>
<Image source={{ uri: item.image }} style={{ width: 100, height: 100, margin: 10 }} />
<View>
<Text style={{ fontSize: 20, fontWeight: 'bold' }}>{item.type}</Text>
<View>
<AntDesign name="star" size={20} color="gold" style={{ marginRight: 10 }} />
<Text style={{ fontSize: 20, fontWeight: 'bold' }}>{item.rating}</Text>
</View>
</View>
</View>
)
}}
/>
<Text style={styles.title}>Address</Text>
<Text style={styles.title}>{address}</Text>
</LinearGradient>
</View>
);
};
Error:
ERROR Warning: React has detected a change in the order of Hooks called by MainMenuScreen. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks
It actually happens because of any bad practice for hook implementations
1 - Only Call Hooks at the Top Level
Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function
NOTE: Implement your useState hooks first at top of the function
2 - Only Call Hooks from React Functions
Don’t call Hooks from regular JavaScript functions
3 - Getting Error during Test
If you get This Error when testing the component, be careful to where you set your custom hooks (replace to top of the function)
Best Practice
use eslint for lint your code avoid geting React Hooks Rules errors
install package with npm or yarn
npm install eslint-plugin-react-hooks --save-dev
I'm building a mobile version of a web app using Material UI and having trouble matching designs. I'm using MUI App-Bar together with MUI Modal to create something similar to the mockups shown below.
The expected behavior is that the user selects the button in the top right of the header to open the modal, and has the option to use the top right button again to close the modal. The user should also be able to select My App logo in the header to navigate to the home page.
The actual behavior is that the header bar is covered by the modal's backdrop; I can add styling like marginTop: 150px to the backdrop to visually achieve the expected result, but the button and the logo are still not usable.
Is there a way to override the backdrop component so that the header will be usable?
const useStyles = makeStyles((theme: Theme) => ({
card: {
position: "absolute",
top: "160px",
width: "90vw",
borderTopLeftRadius: "0px",
borderTopRightRadius: "0px",
},
backDrop: {
marginTop: "160px",
},
}));
const Header = (props) => {
const classes = useStyles();
const [menuOpen, setMenuOpen] = React.useState(false);
const handleOpenUserMenu = () => {
setMenuOpen(true);
};
const handleCloseUserMenu = () => {
setMenuOpen(false);
};
return (
<AppBar
position="static"
style={{
backgroundColor: "#FFFFFF",
zIndex: -1,
}}
>
<Container maxWidth="xl">
<Toolbar>
<Box sx={{ flexGrow: 1 }}>
<Link to={"/home"}>
<Logo className={classes.logo} />
</Link>
</Box>
<Box sx={{ flexGrow: 0 }}>
<IconButton onClick={handleOpenUserMenu}>
<MenuIcon />
</IconButton>
<Modal
open={menuOpen}
onClose={onClose}
BackdropProps={{ classes: { root: classes.backDrop } }}
>
<Card className={classes.card}>
<CardContent>
<MenuItems menuOptions={menuOptions} />
</CardContent>
</Card>
</Modal>
</Box>
</Toolbar>
</Container>
</AppBar>
);
};
As stated in MUIModal documentation the modal component is supposed to behave like that I would try to use menu component instead
Quoting documentation:
If you are creating a modal dialog, you probably want to use the Dialog component rather than directly using Modal. Modal is a lower-level construct that is leveraged by the following components:
Dialog
Drawer
Menu <--
Popover
I am testing my app on android and I have seen that when I scroll down and then to the top of my flatlist, the header (which have an ImageBackground component) is blank (it seems that dissapears when it is not visible in the screen) and then fades in. I don't have this error on iOS, only in android.
Here is the code of the FlatList:
<FlatList
ref={scrollRef}
refreshControl={
<RefreshControl
refreshing={isRefreshing}
colors={[
colors.primary,
colors.pink,
colors.strawberry,
colors.pig,
]}
tintColor={colors.primary}
onRefresh={handleRefresh}
/>
}
ListHeaderComponent={
<View style={styles.headerContainer}>
<Header
uploadProgress={uploadProgress}
onConfigurationButtonPress={handleConfigurationDisplay}
/>
</View>
}
ListFooterComponent={<Tab />}
style={[styles.container, { backgroundColor: colors.white }]}
/>
As you can see, in my flatlist I have two components, a tab in the footer, and a custom component called Header, which code is:
...
<ImageBackground
source={{ uri }}
blurRadius={Platform.OS === "ios" ? 40 : 10}
style={styles.container}
>
<View
style={[styles.overlay, { backgroundColor: colors.transparentWhite }]}
/>
{children}
</ImageBackground>
...
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
},
overlay: {
...StyleSheet.absoluteFillObject,
},
});
Any ideas? Thanks.
I have a component called MDropDowlList which render the following view :
MDropDownList.js
render() {
return (
<View>
<View
style={{
backgroundColor: '#fff',
position: 'absolute',
left: 0,
right: 0,
top: 0,
maxHeight: 200,
}}
>
{
this.props.searchable && (
<TextInput
style={{ zIndex: 198 }}
onChangeText={(text) => this.search(text)}
/>
)
}
<FlatList
data={this.state.data}
keyboardShouldPersistTaps="always"
nestedScrollEnabled={true}
contentContainerStyle={{ zIndex: 199 }}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item, index }) => (
<TouchableHighlight
key={index.toString()}
style={{
padding: 10,
backgroundColor: '#fff',
}}
underlayColor="#5897fb"
onPress={() => this.props.handleOnPress(item)}
>
<MText size={18}>{item}</MText>
</TouchableHighlight>
)}
/>
</View>
</View>
);
}
Then I have called this component to another component called MDropDown which render method is as below :
MDropDown.js
render() {
return (
<View style={{ marginVertical: 5, zIndex: 3}}>
...
{/* Another components */}
...
{
this.state.displayDropDown && (
<MDropDownList data={this.props.data} searchable={this.props.searchable} handleOnPress={(item) => this.handleOnPress(item)} />
)
}
</View>
);
}
Now finally I called my MDropDown component in my main screen as follow :
render() {
return (
<KeyboardAvoidingView style={{ flex: 1, backgroundColor: Colors.bgGray }} behavior="padding">
<ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={styles.container} keyboardShouldPersistTaps="always" nestedScrollEnabled={true}>
<View style={{ backgroundColor: '#fff', padding: 10 }}>
<MDropDown
label="Category"
placeholder="Select Category"
data={["test1", "test2", "test3", "test4", "test5"]}
onSelectItem={(selectedItem) => alert(selectedItem)}
searchable={true}
/>
</View>
</ScrollView>
</KeyboardAvoidingView>
)
}
But I am not able to access Flatlist item or TextInput of MDropDownList component. Even I am not able to focus TextInput available in MDropDownList.
Please help me what's going wrong here ???
Note : This issue is only on android, on ios it is working properly. On ios I am able to click flatlist item and focus TextInput as well as.
Tried using zIndex to the absolute view?
Add property of zIndex : 500 to the style.