TypeError: onChangeImage is not a function. (In 'onChangeImage(result.uri)', 'onChangeImage' is undefined)]

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.

>Solution :

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>
  );
}

Leave a Reply