toggle modal screen from header react native - javascript

Hi I want to toggle a transparent modal screen from the header button, im using hooks
Heres my stack component
function MyStack(props) {
const [modalvisble, setModalvisble] = useState(false)
ToggleModal = () => {
console.log(modalvisble)
setModalvisble(!modalvisble)
}
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="MyTabs"
screenOptions={{
header: ({ ToggleModal }) => {
return (
<Header
ToggleModal={()=>ToggleModal}
/>
)
},
cardStyle: { backgroundColor: 'rgba(52, 52, 52, 0.8)',},
cardStyleInterpolator: ({ current: { progress } }) => ({
cardStyle: {
opacity: progress.interpolate({
inputRange: [0, 0.5, 0.9, 1],
outputRange: [0, 0.25, 0.7, 1],
}),
overlayStyle: {
opacity: progress.interpolate({
inputRange: [0, 1],
outputRange: [0, .5],
extrapolate: 'identity',
})
}
}
})
}}
mode='modal'
>
<Stack.Screen
name="MyTabs"
component={MyTabs}
options={{
}}
/>
<Stack.Screen name="ModalScreen" component={ModalBar} modalvisble={modalvisble} />
</Stack.Navigator>
</NavigationContainer>
);
}
Header Component
function Header({ ToggleModal }) {
//const navigation = useNavigation();
// const toggleIsFocused = () => {
// selected ? navigation.navigate('Mytab') : navigation.navigate('ModalScreen')
// return toggleSelected;
// }
return (
<View>
<View style={{ flexDirection: 'row', alignItems: 'center', marginTop: 30, marginRight: 20, }}>
<Text style={{ color: 'white', margin: 10, fontSize: 13 }}>User Name</Text>
<TouchableOpacity
//onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}
onPress={ ToggleModal}
/>
</View>
</View>
)
}
export default Header;
Modal Screen
function ModalBar({modalvisble}) {
return (
<Modal style={{ flex: 1, }} visible={modalvisble} />
)
}
I try to pass function from parent component to child / or reverse, but still, do not work.
Goal is like using the user name icon to open modal screen for some info, and press again to close modal screen, with same button.
Thanks!!

First, ToggleModal={()=>ToggleModal} this won't actually call ToggleModal function. Instead you should write ToggleModal={() => ToggleModal()}, or just ToggleModal={ToggleModal}.
Second, you dont need to pass ({ ToggleModal }) => {...} as an argument. ToggleModal function is already defined and visible.
Last, you need to use setState(prevState => nextState) form of setState, because otherwise modalVisible will always be seen as true in that function (it won't update, unless you use useCallback) and the function will always set it to false. Here's the code setModalVisible(modalVisible => { return !modalVisible }).

Related

How to create a bottom tab navigation above bottomsheet in react native?

I am trying to create a bottom tab navigation in react native which is having a blur effect but as I am using it above the bottomsheet so navigation bar is getting hide or will have to manage with bottomInset property of bottomsheet.
This is tab navigation coming above bottom sheet
This is actually I want it to look
<BottomSheet
ref={bottomSheetRef}
visible={bottomSheetVisible}
onChangeCallback={onChangeCallback}
enablePanDownToClose={false}
header={header}
bottomInset={84} // due to this I am able to add it above the bottomsheet
style={styles.bottomSheet}
renderBackdrop={renderBackdrop}>
</BottomSheet>
Custom Backdrop
const CustomBackdrop = ({animatedIndex, style}: BottomSheetBackdropProps) => {
// animated variables
const containerAnimatedStyle = useAnimatedStyle(() => ({
opacity: interpolate(
animatedIndex.value,
[1, 1],
[1, 1],
Extrapolate.CLAMP,
),
}));
// styles
const containerStyle = useMemo(
() => [style, styles.container, containerAnimatedStyle],
[style, containerAnimatedStyle],
);
return (
<Animated.View style={containerStyle}>
<View>
<WalletHomeHeader />
<WalletHomeCard />
</View>
<NavigationBar />
</Animated.View>
);
};
export default CustomBackdrop;
const styles = StyleSheet.create({
container: {
flexDirection: 'column',
justifyContent: 'space-between',
},
});
Style in Tab Navigator
tabBarActiveTintColor: theme.white,
tabBarInactiveTintColor: theme.secondaryGrey,
tabBarStyle: {
position: 'absolute',
bottom: 0,
paddingVertical: scaleHeight(15),
backgroundColor: convertHexToRGBA(theme.neutral_700, 0.5),
borderTopWidth: 1,
borderTopColor: theme.grey,
},

Calling useNavigation hook from TouchableOpacity inside a DrawerNavigator from react-navigation pkg throwing error, full source on question body

I'm learning react and react-native last 4 days because need build an mobile app and having the following problem when coding a react-native app:
After some research I found a way to embed a TouchableOpacity inside the top bar of DrawerNavigator, just after the hamburger button and it works giving me an alert.
The problem comes when I try to replace the alert with a call to useNavigation().navigate('Login'); from inside it onPress attribute, it throw the error below.
I want mirror the behavior of menu item on the TouchableOpacity doing the navigation.
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem., js engine: hermes
info Reloading app...
The full source follow as:
import * as React from 'react';
import { Button, Image, StyleSheet, Text, TouchableOpacity, View, Alert } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItemList,
} from '#react-navigation/drawer';
// https://reactnavigation.org/docs/use-navigation/
import { useNavigation } from '#react-navigation/native';
const getScreenCtx = content => {
return (<View style={stl.boxCtx}>{content}</View>);
}
const Home = ({ navigation }) => {
return ( getScreenCtx(<Text style={stl.boxDescr}>Home</Text>) );
}
const Login = ({ navigation }) => {
return ( getScreenCtx(<Text style={stl.boxDescr}>Login</Text>) );
}
const Logout = ({ navigation }) => {
return ( getScreenCtx(<Text style={stl.boxDescr}>Logout</Text>) );
}
const navToLogin = () => {
useNavigation().navigate('Login');
}
const NestedTabBar = props => {
return (
<>
<TouchableOpacity
style={stl.itemNav}
onPress={
() => {
//Alert.alert('NavigateToLogin');
navToLogin();
}
} >
<Text>[NavigateToLogin]</Text>
</TouchableOpacity>
</>
);
}
const ContentTopWideHamburgBar = props => {
return <NestedTabBar />;// <Text style={stl.hamburgBar}>ContentTopHamburgBar</Text>
}
const ContentColapsibleSideBarMenuHeader = props => {
return <Text style={stl.sideMenuHeader}>SideBarMenuHeader</Text>
}
const ContentColapsibleSideBarMenuFooter = props => {
return <Text style={stl.sideMenuFooter}>SideBarMenuFooter</Text>
}
const ContentColapsibleSideBarMenu = props => {
return (
<View style={stl.sideBarMenu}>
<DrawerContentScrollView {...props}>
<ContentColapsibleSideBarMenuHeader/>
<DrawerItemList {...props} />
</DrawerContentScrollView>
<ContentColapsibleSideBarMenuFooter/>
</View>
);
}
const Drawer = createDrawerNavigator();
const ContentItensNavigationRouteMap = () => {
return (
<>
<Drawer.Screen component={Home} name='Home' />
<Drawer.Screen component={Login} name='Login' />
<Drawer.Screen component={Logout} name='Logout' />
</>
);
}
const DrawerNavigator = () => {
return (
<Drawer.Navigator
screenOptions={
{
headerStyle: { backgroundColor: 'magenta', },
headerTintColor: 'white', // hamburg color
headerTitleStyle: { fontWeight: 'bold', },
headerTitle: (props) => <ContentTopWideHamburgBar {...props} />
}
}
contentOptions={
{
activeTintColor: 'red',
activeBackgroundColor: 'red',
inactiveTintColor: 'red',
inactiveBackgroundColor: 'red',
}
}
drawerContent={props => <ContentColapsibleSideBarMenu {...props} />} >
{ContentItensNavigationRouteMap()}
</Drawer.Navigator>
);
};
export default function ShellNavigator() {
return (
<NavigationContainer>
<DrawerNavigator />
</NavigationContainer>
);
}
const stl = StyleSheet.create({
boxDescr: {
fontSize: 30,
margin: 10,
padding:10,
backgroundColor: 'lightblue',
color: 'red',
},
boxCtx:{
display: 'flex',
flex: 1,
fontSize: 30,
margin: 0,
backgroundColor: 'yellow',
},
hamburgBar: {
fontSize: 20,
margin: 10,
backgroundColor: 'pink',
},
sideMenuHeader: {
fontSize: 20,
margin: 10,
backgroundColor: 'blueviolet',
},
sideMenuFooter: {
fontSize: 20,
margin: 10,
backgroundColor: 'purple',
},
sideBarMenu: {
flex: 1,
fontSize: 20,
margin: 10,
backgroundColor: 'greenyellow',
},
itemNav: {
fontSize: 40,
padding: 10,
backgroundColor: 'red',
},
});
Here navToLogin is a stand alone function, not in a Functional component. Hooks need to be in a functional component to use. The bellow code should work which navToLogin move the function inside a functional component.
const NestedTabBar = props => {
const navigation = useNavigation();
const navToLogin = () => {
navigation.navigate('Login');
}
return (
<>
<TouchableOpacity
style={stl.itemNav}
onPress={
() => {
//Alert.alert('NavigateToLogin');
navToLogin();
}
} >
<Text>[NavigateToLogin]</Text>
</TouchableOpacity>
</>
);
}

Weird padding on View in react native web on Edge

I was creating a Button in react native (on web). If I view the button in Edge, a very weird padding appears. I tried to debug but I can't get a fix. It works correctly on Android and Firefox.
I think there is some problem with Edge's renderer (Blink) because the code works correctly in firefox and on android (native).
Here is the code for the component:
import React, { useState } from 'react';
import { View, Animated, Easing, Image, StyleSheet, Pressable, Text } from 'react-native';
import { Hoverable } from 'react-native-web-hooks';
const Button = () => {
const [animatedButtonPressed] = useState(new Animated.Value(0));
const [animatedButtonHover] = useState(new Animated.Value(0));
const animate = (value, toValue, duration = 150, easing = Easing.linear) => {
Animated.timing(value, {
toValue: toValue,
duration: duration,
easing: easing,
// change later
useNativeDriver: false
}).start();
}
const animatedTextStyle = {
color: animatedButtonPressed.interpolate({
inputRange: [0,1],
outputRange: ["#fff" , "#2b7f3c"]
})
}
const animatedButtonStyle = {
backgroundColor: animatedButtonHover.interpolate({
inputRange: [0,1],
outputRange: ["#2b7f3c", "transparent"]
}),
}
const animatedButtonPressedStyle = {
backgroundColor: animatedButtonPressed.interpolate({
inputRange: [0,1],
outputRange: ["#fff", "red"]
}),
}
let Handlers = (props) => {
return (
<>
<Pressable onPressIn={() => animate(animatedButtonPressed, 1)} onPressOut={() => animate(animatedButtonPressed, 0)}>
<Hoverable onHoverIn={() => animate(animatedButtonHover, 1)} onHoverOut={() => animate(animatedButtonHover, 0)}>
<View {...props}/>
</Hoverable>
</Pressable>
</>
)
}
let Backgrounds = (props) => {
return (
<Animated.View style={animatedButtonPressedStyle}>
<Animated.View style={animatedButtonStyle}>
<View {...props}/>
</Animated.View>
</Animated.View>
)
}
return (
<View style={styles.container}>
<View style={styles.button}>
<Backgrounds>
<Handlers>
<View style={styles.padding}>
<Animated.Text style={[styles.text, animatedTextStyle]}>Hello</Animated.Text>
</View>
</Handlers>
</Backgrounds>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignSelf: 'flex-start',
overflow: 'hidden',
},
button: {
borderRadius: 3,
borderWidth: 2,
borderColor: 'green',
},
padding: {
paddingHorizontal: 10,
paddingVertical: 5,
},
text: {
color: 'white',
fontSize: 16
}
});
export default Button;
I think this is unfortunately a symptom of using React-native on the web things get squashed and you won't have as much control for cross browser quirks.
Is there any reason you didn't use ReactJS?

How to animate my header (reduce its height) as i scroll through my Flatlist?

can you see what i'm doing wrong here in animating my flatlist?
The this.animatedHeaderHeight picks up my start and end header height fine, but when i scroll up and down in the flatllist, the header doesn't change it's height whatsoever! Help!
export default class MyClass extends Component {
componentWillMount = async () => {
/***** Animated scrolling hide profile info ****/
this.scrollY = new Animated.Value(0)
this.startHeaderHeight = 250 //(ITEM_HEIGHT/4)
this.endHeaderHeight = 50 //(ITEM_HEIGHT/7)
this.animatedHeaderHeight = this.scrollY.interpolate({
inputRange: [0, 50],
outputRange: [this.startHeaderHeight, this.endHeaderHeight],
extraploate: 'clamp'
})
}
render() {
return (
<SafeAreaView style={styles.profileContainer}>
<Animated.View style={[styles.HeaderArea, { height: this.animatedHeaderHeight, backgroundColor: 'orange' }]}>
<View style={styles.uploaderPic}>
<Text> HELLO </Text>
</View>
</Animated.View>
<View style={styles.grid}>
<ScrollView scrollEventThrottle={16}>
<FlatList
numColumns={columns}
data={myArray}
onScroll={Animated.event(
[
{ nativeEvent: { contentOffset: { y: this.scrollY } } },
{ useNativeDriver: true }
]
)}
keyExtractor={(item, index) => { return index }}
renderItem={...}
/>
</ScrollView>
</View>
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
profileContainer: {
flex: 1,
},
HeaderArea: {},
uploaderPic: {},
grid: {
flex: 3,
flexDirection: 'column',
},
});

How to search through items?

Home.js
I am using my own search Icon not,from react native elements..I dont know how to do search through items I m getting from the backend...
this.state = {
data: [],
isLoading: true
}
componentDidMount(){
API.get_products()
.then((products) => {
this.setState({
data: products.data,
isLoading: false
});
})
.catch(err => alert(err.message));
}
Search.js
render() {
if (this.state.showSearchBar) {
return <TextInput
style={{width: width, backgroundColor: 'white', fontSize: 18, paddingLeft: 10}}
placeholder={'Search'}
/>
}
return(
<View>
<TouchableOpacity
onPress={() => {
this.setState({showSearchBar: true})
}}
>
<Image
source={require('../images/tabs/search.png')}
style={{height: 40, width: 60}}
resizeMode={'contain'}
/>
</TouchableOpacity>
</View>
)
App.js
Here's the home page.which gives the ability to navigate
const Inside = TabNavigator(
{
Home: {
screen: Home,
navigationOptions: {
headerLeft: null,
headerTitle: "Blue Rocker",
headerRight: <Search/>,
}})
Your question is unclear and it misses informations... If you want to read all your data information, please give us the structure of your data at least.
Since it will certainly be json, you can use the method filter() as so:
var filteredItems = data.filter(function(yourElement) {
return yourElement.aCertainValue == yourInputTextString;
})

Categories