how to change useState's state without render in functional component
const [imageId, setimageId] = useState(0);
const Slide = () => {
return (
slides.map((item, index) => (
<View style={styles.slide}>
<TouchableOpacity onPress={()=>setimageId(index)} >
<Image source={item.image}} />
</TouchableOpacity>
</View>
))
)
}
when I change state in onPress slide component re-renders and images load again
so how can I change the state without rendering the slide component
You would need to create a component that will be inside the slides.map(...) and will have its own state.
If you change the state of Slide it will render the component Slide, that's basically the idea of the hook useState.
You can check the useRef docs also. When you want to change a value in the component without rendering you usually want to the useRef hook, not the useState
Related
New to react native and in a component, I have a list of views that include a checkbox (react-native-bouncy-checkbox). Each view is wrapped in a TouchableWithoutFeedback(So I can click the entire view, not just the checkbox) and I have a boolean useState to tell the checkbox whether to display the check or not.
The issue I'm at is that I chose the library for the checkbox because the animation when it's clicked looks very nice. However, the animation doesn't play if I hit the view ~ only if I hit the actual checkbox, which is rather small in my app.
Is there any way to tell another component that it needs to act like it was pressed, so it can play its animation?
Code for clarity:
const Task = ({ id, text }: Types) => {
const [checked, setChecked] = React.useState(false);
return (
<TouchableWithoutFeedback onPress={() => setChecked(!checked)}>
<View style={styles.container} >
<BouncyCheckbox
disableBuiltInState={true}
isChecked={checked}
fillColor="blue"
iconStyle={{ borderColor: 'gray' }}
/>
<Text>{text}</Text>
</View>
</TouchableWithoutFeedback>
)
};
Okay figured it out. Apparently React native allows you to create refs to other components and you can use the reference.onPress() to activate the animation.
When I use props.navigation.navigate("example"), it works normally. But if I import the component on another page it doesn't work anymore, props returns an empty object.
Works Fine:
const Menu = props =>{
console.log(props)
return(
<View style={styles.menuStyle}>
<TouchableOpacity style={styles.topicDiv} onPress={() =>props.navigation.navigate("Ads")}>
<View>
<Image style={styles.topicStyle} source={require ("../assets/security-camera.png")}/>
<Text style={styles.textStyle}>Câmeras</Text>
<Text style={styles.subTextStyle}>Veja como está a praia ao vivo 📷</Text>
If i try import Menu, navigation does not work:
import React from "react";
import { View } from "react-native";
import Menu from "./menu";
const Supermenu = () =>{
return(
<View>
<Menu></Menu>
</View>
)
}
export default Supermenu
If you use <Menu> inside of another component like <Supermenu>, React Navigation has no way to pass its navigation property in there. It only happens automatically if a component is a direct child of a screen (or its component property).
To have navigation available in Menu regardless of its position in the hierarchy, as long as it's a child of <NavigationContainer>, the best way is to make use of the useNavigation hook:
import { useNavigation } from '#react-navigation/core';
const Menu = props =>{
const navigation = useNavigation();
return (
<View style={styles.menuStyle}>
<TouchableOpacity style={styles.topicDiv} onPress={() => navigation.navigate("Ads")}>
...
See documentation for more detail.
If you are on an older version, there was also a HOC withNavigation that you could use.
You could also do the same in Supermenu and then pass navigation down manually.
use import {userNavigation} from '#react-navigation/core' instead of props navigate or you can add navigation props to the Menu component.
I am new to react native. What I want to achieve is that I want to navigate between screen while using pressable. What i have done is I have already created pressable button components inside buttons.js file what I want right now is that when I call that component inside of a file I want to pass screen name as a prop to that button component and navigate between screen using that main component. In short what i mean is whenever a screen name is passed from different file it act according to that and instead I don`t have to create multiple navigation inside each file.
E.g
Inside Home file
<ButtonXsPrimary
title='Login'
/>
Inside Buttons.js file
const ButtonXsPrimary = (prop) => {
const navigation = useNavigation();
return (
<>
<Pressable style={[style.buttonXs, Color.bgSecondry]} onPress={() => navigation.navigate(prop)} >
<Text style={[Color.White, style.buttonsTextSm]}>{prop.title}</Text>
</Pressable>
</>
);
};
The same title prop is used for navigation
As I understand you can do this way,
You need to pass navigation and route name as a prop inside your ButtonXsPrimary like
<ButtonXsPrimary
title="Login"
navigation={navigation}
routeName={'YourRouteName'}
/>
Access the props
onPress={() => prop.navigation.navigate(prop.routeName)}
So I have a component with ScrollView which contains many elements, so you have to scroll a long way down.
Now there should be a button at the bottom of the page that on click will scroll the page back to top.
I already created the button as a FAB (floating action button) in an extra component.
It is integrated in a parent component, where the ScrollView is located.
What I found was that you have to create a ref in the ScrollView component and implement a button right there that uses this ref to make scrolling work. Simplified, here is what I have so far:
imports ...
const ParentComponent: React.FC<Props> = () => {
const scroll = React.createRef();
return (
<View>
<ScrollView ref={scroll}>
<SearchResult></SearchResult> // creates a very long list
<FloatingButton
onPress={() => scroll.current.scrollTo(0)}></FloatingButton>
</ScrollView>
</View>
);
};
export default ParentComponent;
As you can see, there is the component FloatingButton with the onPress() method.
Here is the implementation:
import React, {useState} from 'react';
import {Container, Content, Button, Icon, Fab} from 'native-base';
const FloatingButton: React.FC<Props> = () => {
return (
<Fab
position="bottomRight"
onPress={(???}>
<Icon name="arrow-round-up" />
</Fab>
);
};
export default FloatingButton;
Now the problem: Where should I do the onPress() method? Because if I leave it in the parent component, it won't work because it is not directly located in the Fab (in FloatingButton). I would like to do the onPress() logic in Fab, but if I do so, the ScrollView that it needs is not available, because it's in the parent component. My idea was to maybe passing the ref as prop into FloatingButton, but for some reason this didn't work.
Can someone please help me?
You could either let the parent hook into the FloatingButton's onPress function or pass the ref down to the FloatingButton directly.
export const Parent : FC<ParentProps> = props => {
const scrollRef = useRef<ScrollView>();
const onFabPress = () => {
scrollRef.current?.scrollTo({
y : 0,
animated : true
});
}
return (
<View>
<ScrollView ref={scrollRef}>
{/* Your content here */}
</ScrollView>
<FloatingButton onPress={onFabPress} />
</View>
);
}
export const FloatingButton : FC<FloatingButtonProps> = props => {
const { onPress } = props;
const onFabPress = () => {
// Do whatever logic you need to
// ...
onPress();
}
return (
<Fab position="bottomRight" onPress={onFabPress}>
<Icon name="arrow-round-up" />
</Fab>
);
}
You should determine the horizontal or vertical value you want to scroll to, like this code snippet.
onPress={()=>
this.scroll.current.scrollTo({ x:0, y:0 });
}
Please have a look at my snack code. Hope it might be helpful for you.
https://snack.expo.io/#anurodhs2/restless-edamame
I want to pass data to another component but not like this.
return (
<View style = {{flex:1}}>
---> <LoginForm profile = {this.state.values}/> // I dont want to send like this
<Animated.View style={{ ...this.props.style, opacity: fadeAnim }} >
{this.props.children}
</Animated.View>
</View>
);
because if I do like this, this component includes LoginForm as well. and also I dont want to send with navigate. Because I dont want to open that component on screen. when I work in this screen I just want to send values to another component
You need to pass a function to mutate the state from LoginForm to this child component.
On LoginForm,
<View>
...
<ChildComponent changeProfile={(profile) => {
this.setState({
profile: profile
})
}}/>
</View>
then on this ChildComponent, call
this.props.changeProfile(this.state.values);
Or you can try a state management library too, like Redux or MobX. Personally, I prefer Redux.