I'm new to app development and React Native, and I'm writing my code following a tutorial. I have an image selector that opens the phone's gallery, but when I select an image I get this error every time.
Error reading an image [TypeError: onChangeImage is not a function. (In 'onChangeImage(result.uri)', 'onChangeImage' is undefined)]
This is my ImageInput.js script:
import React, { useEffect } from "react";
import {
View,
StyleSheet,
Image,
TouchableWithoutFeedback,
Alert,
} from "react-native";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import * as ImagePicker from "expo-image-picker";
import colors from "../config/colors";
function ImageInput({ imageUri, onChangeImage }) {
useEffect(() => {
requestPermission();
}, []);
const requestPermission = async () => {
const { granted } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (!granted) alert("You need to enable permission to access the library.");
};
const handlePress = () => {
if (!imageUri) selectImage();
else
Alert.alert("Delete", "Are you sure you want to delete this image?", [
{ text: "Yes", onPress: () => onChangeImage(null) },
{ text: "No" },
]);
};
const selectImage = async () => {
try {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 0.5,
});
if (!result.cancelled) onChangeImage(result.uri);
} catch (error) {
console.log("Error reading an image", error);
throw error;
}
};
return (
<TouchableWithoutFeedback onPress={handlePress}>
<View style={styles.container}>
{!imageUri && (
<MaterialCommunityIcons
color={colors.medium}
name="camera"
size={40}
/>
)}
{imageUri && <Image source={{ uri: imageUri }} style={styles.image} />}
</View>
</TouchableWithoutFeedback>
);
}
const styles = StyleSheet.create({
container: {
alignItems: "center",
backgroundColor: colors.light,
borderRadius: 15,
height: 100,
justifyContent: "center",
marginVertical: 10,
overflow: "hidden",
width: 100,
},
image: {
height: "100%",
width: "100%",
},
});
export default ImageInput;
And this is App.js script:
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
Button,
Alert
} from 'react-native';
import Screen from "./app/components/Screen";
//import * as ImagePicker from "./app/components/ImagePicker";
import * as ImagePicker from "expo-image-picker";
import ImageInput from "./app/components/ImageInput";
export default function App() {
const [imageUri, setImageUri]= useState();
const requestPermission=async () => {
const{ granted } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (!granted)
alert('You need to enable permissions to access the library')
}
useEffect(()=> {
requestPermission();
},[]);
const selectImage = async () => {
try {
const result= await ImagePicker.launchImageLibraryAsync();
if(!result.cancelled)
setImageUri(result.uri);
} catch (error) {
console.log('Error Reading an Image')
}
}
return <Screen>
<Button title ="Select Image" onPress={selectImage} />
<Image source = {{uri: imageUri }} style={{ width: 200, height: 200 }} />
<ImageInput />
</Screen>;
}
This is what i get in the terminal:
Error reading an image [TypeError: onChangeImage is not a function. (In 'onChangeImage(result.uri)', 'onChangeImage' is undefined)]
[Unhandled promise rejection: TypeError: onChangeImage is not a function. (In 'onChangeImage(result.uri)', 'onChangeImage' is undefined)]
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:86:13 in tryCatch
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:66:31 in <anonymous>
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:86:13 in tryCatch
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:124:27 in invoke
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:130:16 in PromiseImpl.resolve.then$argument_0
at node_modules\react-native\node_modules\promise\setimmediate\core.js:37:13 in tryCallOne
at node_modules\react-native\node_modules\promise\setimmediate\core.js:123:24 in setImmediate$argument_0
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:248:12 in _allocateCallback$argument_0
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:112:14 in _callTimer
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:162:14 in _callReactNativeMicrotasksPass
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:413:41 in callReactNativeMicrotasks
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:391:6 in __callReactNativeMicrotasks
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:133:6 in __guard$argument_0
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:368:10 in __guard
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:132:4 in flushedQueue
I tried to fix it following the answer provided to this question but it did not work for me.
CodePudding user response:
you have to declare it in App.js
export default function App() {
// ...
return (
<Screen>
<Button title="Select Image" onPress={selectImage} />
<Image source={{ uri: imageUri }} style={{ width: 200, height: 200 }} />
<ImageInput
imageUri={any}
onChangeImage={() => {
// functions
}}
/>
</Screen>
);
}