How to change image when a button is clicked on Expo? - reactjs

I am trying to make an app that shows cat pictures on Expo. I have a cat picture that is displayed originally. I have a button and when I click the button, I want to change the cat picture that is displayed. Here is what I have:
let imageUri = {uri: 'https://images.unsplash.com/photo-1615789591457-74a63395c990?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8ZG9tZXN0aWMlMjBjYXR8ZW58MHx8MHx8&w=1000&q=80'};
I define a function that changes the imageUri value:
const displayImage = async () => {
imageUri = {uri: 'https://images.unsplash.com/photo-1529778873920-4da4926a72c2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8Y3V0ZSUyMGNhdHxlbnwwfHwwfHw%3D&w=1000&q=80'}
}
Then inside of return() I do the following:
<View style={styles.container}>
<ImageBackground
source={require('./assets/images/background.png')}
style={styles.image}
/>
<Text style={styles.text}> Here is a cat picture </Text>
<Button
style = {styles.button}
title="Display"
onPress = {() => displayImage()}
/>
<Image source={imageUri} style = {{width: 155, height: 259}} />
</View>
However, it does not update the picture.

The reason your image is not changing is becuase the state of the component is not changing. To solve this you need to manage the state of the component data. You can do this with the hook useState.
Make sure to import useState hook.
import {useState} from 'react';
Then you can set a state managed variable for your image.
const [imageUri, setImageUri] = useState(
'https://images.unsplash.com/photo-1615789591457-74a63395c990?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8ZG9tZXN0aWMlMjBjYXR8ZW58MHx8MHx8&w=1000&q=80'
);
Then all you need is to update your button press event to call the state hook to set the new image into state. So when the image changes your components state updates with the new image.
<View style={styles.container}>
<ImageBackground
source={require('./assets/images/background.png')}
style={styles.image}
/>
<Text style={styles.text}> Here is a cat picture </Text>
<Button
style = {styles.button}
title="Display"
onPress = {() => setImageUri('https://images.unsplash.com/photo-1529778873920-4da4926a72c2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8Y3V0ZSUyMGNhdHxlbnwwfHwwfHw%3D&w=1000&q=80')}
/>
<Image source={imageUri} style = {{width: 155, height: 259}} />
</View>

Related

How can I open BottomSheetModal (#gorhom/bottom-sheet) in different component, using React-Native (Expo)

I am using https://gorhom.github.io/react-native-bottom-sheet/.
I was wondering how can I open "BottomSheetModal" in a different file e.g Navbar Component.
This is what my code looks like at the moment to open the Bottom Sheet inside of the same component.
const BottomSheetModal: FC = () => {
const bottomSheetModalRef = useRef<BottomSheet>(null);
const snapPoints = useMemo(() => ["25%", "50%"], []);
const handlePresentModalPress = useCallback(() => {
bottomSheetModalRef.current?.present();
}, []);
return (
<>
<Button title="Test" onPress={() => handlePresentModalPress()} />
<BottomSheet
index={1}
style={{ ...shadows.bottomSheet }}
ref={bottomSheetModalRef}
snapPoints={snapPoints}>
<View style={styles.container}>
<Text>Awesome 🎉</Text>
</View>
</BottomSheet>
</>
);
};
So how can I use the opening code of the Bottom Sheet inside of my Navbar Component?
Navbar Component:
// Open BottomSheet here
<TouchableWithoutFeedback onPress={() => openBottomSheet()}>
<View>
<Image
style={styles.avatar}
source={{
uri: "https://lumiere-a.akamaihd.net/v1/images/character_themuppets_kermit_b77a431b.jpeg?region=0%2C0%2C450%2C450",
}}
/>
</View>
</TouchableWithoutFeedback>
Thank you!
I found out to do this, incase anyone comes across this question, I'll post it here!
So what you have to do is pass the ref to the bottom sheet component. So in the Navbar component I created the ref for the bottom sheet, and then passed it into the bottom sheet.
Navbar:
// Create Ref
const userBottomSheetRef = useRef<BottomSheetModal>(null);
// Pass ref into the bottom sheet component
<BottomSheet ref={userBottomSheetRef} snapPoints={["30%"]}/>
Then inside the bottom sheet component you forward the ref using a react function, and then pass it in as normal:
<BottomSheetModal ref={ref} >
<BottomSheetScrollView>
<View style={styles.container}>{children}</View>
</BottomSheetScrollView>
</BottomSheetModal>

Changing content of a component with each swipe of Swiper Library

I am new to React Native and am not completely familiar with state management. Currently I am using react-native-swiper library to hold my swipable images. Each swipe takes me to the next image. Code below
Fish.js:
<Swiper style={styles.wrapper} height={10} horizontal={true} >
<View style={styles.slide1}>
<Image
resizeMode="stretch"
style={styles.image}
source={require('../resource/images/AzureDamsel.png')}
/>
</View>
<View style={styles.slide2}>
<Image
resizeMode="stretch"
style={styles.image}
source={require('../resource/images/BicolourAngelfish.png')}
/>
</View>
<View style={styles.slide3}>
<Image
resizeMode="stretch"
style={styles.image}
source={require('../resource/images/ClownTriggerfish.png')}
/>
</View>
</Swiper>
And I am importing this in my App.js where I have some Text component below this like so:
<View style={{ flex: 1 }}>
<ImageBackground
style={globalStyles.backgroundImage}
source={require('./resource/images/bg1080.jpeg')}
>
<Fish />
<Text> Fish 1</Text>
<Text> Fish 2</Text>
</ImageBackground>
</View>
But I want the respective Text to show with each swipe. Example at image 1 the Text says Fish 1, then when I swipe the image and go to the second slide, the Text changes to Fish 2 and so on. Any help would be appreciated.
You can maintain the active slide index in state and then render that index.
Inside of App.js
const [activeIndex, setActiveIndex] = useState();
const onIndexChanged = (index) => setActiveIndex(index);
return (
<View>
<Fish
onIndexChanged={onIndexChanged}
/>
{ activeIndex && <Text>`Fish ${activeIndex}`</Text> }
</View>
)
Inside of Fish.js you need to pass the onIndexChanged prop into Swiper.
const Fish = ({ onIndexChanged }) => (
<Swiper onIndexChange={onIndexChanged}>
// Rest of your code.
</Swiper>
)
Checking your Snack, I can see some output but as you mentioned it's not what you are expecting.
Start the activeIndex state variable to 0.
const [activeIndex, setActiveIndex] = useState(0);
Pass setActiveIndex straight into Fish via the onIndexChanged prop. Now you will be able to remove the unnecessary onIndexChanged function from App.js
<Fish onIndexChanged={setActiveIndex} />
Change your string interpolation to just render the text from fishMapping. Because activeIndex is no longer undefined, you do not need the additional check (activeIndex &&)
<Text>{fishMapping[activeIndex]}</Text>
Here's an updated version of your Snack.
I went through the snack provided by you and the issue is in the Fish.js file.
Replace onIndexChange with onIndexChanged. The updated code:
const Fish = ({ onIndexChanged }) => (
<Swiper onIndexChanged={onIndexChanged}>
// Rest of your code.
</Swiper>
)
Link to updated snack : https://snack.expo.dev/BToSGo1z6

How to send values without navigating to child component

good morning
I wanted to send some array data to child component , the purpose of this component is to make my code in one page shorter
this page i named it homepage, inside homepage there are multiple charts
import Chart01 from ../components/chart01
import Chart02 from ../components/chart02
import Chart03 from ../components/chart03
and in this homepage there will be buttons that (I'm planning to) send value to those 3 charts
const [FirstValue,setFirstValue] = useState(0)
return(
<View>
<View>
<Button onPress={()=>setFirstValue(1)}
<Button onPress={()=>setFirstValue(2)}
<Button onPress={()=>setFirstValue(3)}
</View>
<Chart01/>
<Chart02/>
<Chart03/>
</View>
)
How do i send the FirstValue from HomePage to Chart01 Chart02 Chart03 ?
and in Chart01, how do I call value that sent from HomePage ?
Thank you
In home you have pass like below,
<Chart01 value={FirstValue}/>
<Chart02 value={FirstValue}/>
<Chart03 value={FirstValue}/>
In Chart01,02,03 definition, you have to read props.
const Chart01 = (props) => {
const { value } = props;
// someting
};
Pass the values as props to the chart components.
const [firstValue, setFirstValue] = useState(0);
return(
<View>
<View>
<Button onPress={() => setFirstValue(1)}
<Button onPress={() => setFirstValue(2)}
<Button onPress={() => setFirstValue(3)}
</View>
<Chart01 value={firstValue} />
<Chart02 value={firstValue} />
<Chart03 value={firstValue} />
</View>
);
Within the chart components you can access the passed value from the value prop (or whatever you name it). For example:
props.value

Change state from custom button in React Native

I'm just starting at React native and i want to update the state from my home page with a click on a custom button.
I made this code juste bellow. When I click on my buttons, i can't see the state change.
const Home = () => {
const welcomeSentence =
"Bonjour, est ce que tu as fais ton workout aujourd'hui ?";
const [isWorkoutDone, setIsWorkoutDone] = useState(false);
return (
<View style={styles.container}>
<Text style={styles.homePageText}>{welcomeSentence}</Text>
<View style={styles.buttonContainer}>
<AppButton title ="OUI" onPress={()=>this.setIsWorkoutDone(true)}/>
<AppButton title ="NON" onPress={()=>this.setIsWorkoutDone(false)}/>
</View>
<Text>{isWorkoutDone ? "OK" : "KO"}</Text>
</View>
);
};
With this code on my cutom button :
const AppButton = (props) => {
return (
<Button
title={props.title}
onPress={props.onPress}
style={styles.appButton}
/>
);
};
I tested and make search but I didn't find why my state didn't change.
You are using functional component so you don't need this.
<AppButton title ="OUI" onPress={()=>setIsWorkoutDone(true)}/>
<AppButton title ="NON" onPress={()=>setIsWorkoutDone(false)}/>

react native TouchableOpacity on press issue

I have a modal - react-native-modal - I want when it pops up and the user pressed out of the modal's Box that should disappear the modal , so i have used TouchableOpacity it works only if you click inside the box please see my image attached file.
this is my code :
import Modal from 'react-native-modal';
const TeskModal = ({isVisibles, onCallBaclk, deleteCurrenteTask , hideit}) => (
<View>
<TouchableOpacity onPress ={ () => hideit()}>
<Modal
isVisible = {isVisibles}
animationIn = {'zoomInDown'}
animationOut = {'zoomOutUp'}
animationInTiming = {500}
animationOutTiming = {500}
backdropTransitionInTiming = {1000}
backdropTransitionOutTiming = {1000}
>
<TouchableOpacity onPress ={ () => hideit()}>
<View style={style.modal}>
<View style={style.textView}>
<Text>
Change State Or Delete.
</Text>
</View>
<View style = {style.buttonView} >
<Button style={style.buttonChangeStatus} title ="Delete Task" onPress ={ () => deleteCurrenteTask()} />
<Button style={style.buttondelete} title = " Change State" onPress ={ () => onCallBaclk()} />
</View>
</View>
</TouchableOpacity>
</Modal>
</TouchableOpacity>
</View>
);
export default TeskModal;
here is my image
could you please help me to solve this issue.
There is a function called onBackdropPress in react-native-modal. You can call a function when the backdrop(i.e. outside the area of the modal) is pressed.
<Modal
{... otherProps }
onBackdropPress = {() => hideIt()}
/>
The above code will do it fo you.
There is a prop that you can pass which will take care of performing the function that you pass to the prop in case user press outside of the modal box. This way you will not need hideit()}> etc.
eg:
<Modal
isVisible={isVisible}
{...otherProps}
onBackdropPress={this.hideit()}>
{...content}
</Modal>
I hope this helps. Please let me know if this is what you are looking for.

Resources