I’m learning react-native/expo and I’m stuck on this problem for hours.
So when I type anything, the whole page re-renders. I know that because in the code I upload an image and in console I see the image uri. So when I type, I see it again and again until the app crashes.
I uploaded here the whole code because it’s too long.
The flow is – Fill the form – upload image if needed – press the confirm button
I tried using useCallback
, but with no success.
MRE as requested
import React, { useState, useCallback } from 'react';
import { View, TextInput, Text, StyleSheet, TouchableOpacity, Image } from 'react-native';
import KeyboardWrapper from '../KeyboardWrapper';
import * as ImagePicker from 'expo-image-picker';
const FormComponent = ({ onSave }) => {
const [formData, setFormData] = useState({
driverName1: '',
});
const [images, setImages] = useState([]); // State to store captured images
// Function to handle image capture
const handleCaptureImage = useCallback(async () => {
const { status } = await ImagePicker.requestCameraPermissionsAsync();
if (status !== 'granted') {
alert('Camera permission is required to take pictures.');
return;
}
try {
const result = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: false,
aspect: [16, 9],
quality: 1,
});
if (!result.cancelled && result.assets.length > 0) {
// Add the new image URI to the images state
setImages(prevImages => [...prevImages, result.assets[0].uri]);
}
} catch (error) {
console.error('Error capturing image:', error);
}
}, []);
const handleChange = useCallback((name, value) => {
setFormData({ ...formData, [name]: value });
}, [formData]);
return (
<KeyboardWrapper>
<View style={styles.container}>
<View style={styles.form}>
<TextInput
placeholder="Sofer 1"
value={formData.driverName1}
onChangeText={(text) => handleChange('driverName1', text)}
style={styles.textInput}
/>
{/* Display captured images */}
<View style={styles.formImgs}>
{images.map((imageUri, index) => (
<View key={index} style={styles.img}>
{console.log('Image URI:', imageUri)}
<Image
source={{ uri: imageUri }}
style={{ width: 100, height: 100 }}
/>
</View>
))}
</View>
<View style={styles.formAction}>
<TouchableOpacity onPress={handleCaptureImage}>
<View style={styles.btn}>
<Text style={styles.btnText}>Scaneaza</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
</KeyboardWrapper>
);
};
2
Answers
the problem is with handlechange it should be like this
I believe the component re-rendering is a default feature of React. If you want more granular control over when your component re-renders, you’re probably looking for
React.memo
. Wrapping a component in this will prevent it from rerendering by default.And the same demo, but without memo so you can see the log happening when input changes.