'Camera not working with React Native Expo: Invalid Hook Call
I'm trying to get camera working in my RN Expo app, but I'm getting an error. The error is telling me I am using hooks, how I'm using class component and not using hooks (as far as I'm aware!?)
I've added the code and error log below. Can anyone help? Thanks in advance...
Update Photo component, which launches the camera and handles the image processing
class UpdatePhoto extends Component {
constructor(props) {
super(props);
this.state = {
hasPermission: null,
type: Camera.Constants.Type.back,
};
}
async componentDidMount() {
const { status } = await Camera.requestCameraPermissionsAsync();
this.setState({ hasPermission: status === "granted" });
}
takePicture = async () => {
if (this.camera) {
const options = {
quality: 0.5,
base64: true,
onPictureSaved: (data) => this.sendPhotoToServer(data),
};
const data = await this.camera.takePictureAsync(options);
console.log(data.uri);
}
};
sendPhotoToServer = async (data) => {
const id = await getUserId();
const token = await getAuthToken();
const rawFile = await fetch(data.base64);
const blob = await rawFile.blob();
return fetch(`http://localhost:3333/api/1.0.0/user/${id}/photo/`, {
method: "POST",
headers: {
"Content-Type": "image/png",
"X-Authorization": token,
},
body: blob,
})
.then((response) => {
console.log("Picture added", response);
})
.catch((err) => {
console.log(err);
});
};
render() {
if (this.state.hasPermission) {
return (
<View style={styles.container}>
<Camera
style={styles.camera}
type={this.state.type}
ref={ref => this.camera = ref}
>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.button}
onPress={() => {
this.takePicture();
}}
>
<Text style={styles.text}>Take Picture</Text>
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
return <Text>No access to camera</Text>;
}
}
export default UpdatePhoto;
Component JS screen, including the 'Update Photo' button which launches Update Photo component through navigation.navigate
class MyProfile extends React.Component {
constructor(props) {
super(props);
this.state = {
firstName: "",
lastName: "",
emailAddress: "",
photo: null,
isLoading: true,
postList: [],
};
}
componentDidMount() {
getProfilePhoto()
.then((response) => {
return response.blob();
})
.then((responseBlob) => {
const data = URL.createObjectURL(responseBlob);
this.setState({
photo: data,
isLoading: false,
});
})
.catch((error) => {
console.log(error);
});
getUserData()
.then((response) => response.json())
.then((responseJson) => {
this.setState({
firstName: responseJson.first_name,
lastName: responseJson.last_name,
emailAddress: responseJson.email,
});
})
.catch((error) => {
console.log(error);
});
this.getPosts();
}
getPosts = async () => {
const token = await getAuthToken();
const id = await getUserId();
return fetch(`http://localhost:3333/api/1.0.0/user/${id}/post`, {
headers: {
"X-Authorization": token,
},
})
.then((response) => {
if (response.status === 200) {
return response.json();
}
})
.then((responseJson) => {
console.log("GET/user/user_id/post response");
console.log(responseJson);
this.setState({
isLoading: false,
postList: responseJson,
});
})
.catch((error) => {
console.log(error);
});
}
deletePost = async (post_id) => {
const token = await getAuthToken();
const id = await getUserId();
const postId = await getPostId();
console.log('Post id: ' + post_id);
return fetch(`http://localhost:3333/api/1.0.0/user/${id}/post/${post_id}`, {
method: "DELETE",
headers: {
"X-Authorization": token,
},
})
.then((response) => {
if (response.status === 200) {
console.log(`Post ${postId} deleted`);
this.getPosts();
} else {
console.log(response.status);
}
})
.catch((error) => {
console.log(error);
});
}
render() {
if (!this.state.isLoading) {
return (
<View>
<View style={GlobalStyles.container}>
<Text style={GlobalStyles.screenTitle}>MY PROFILE</Text>
</View>
<View style={GlobalStyles.container}>
<Image
source={{
uri: this.state.photo,
}}
style={{
width: 350,
height: 300,
borderWidth: 5,
}}
/>
</View>
<Text
style={GlobalStyles.textInput}
>{`${this.state.firstName} ${this.state.lastName}`}</Text>
<Text
style={GlobalStyles.textInput}
>{`${this.state.emailAddress}`}</Text>
<View style={GlobalStyles.smallButtonContainer}>
<TouchableOpacity
style={GlobalStyles.smallButton}
onPress={() => {
this.props.navigation.navigate("MyDetails");
}}
>
<Text style={GlobalStyles.buttonText}>EDIT DETAILS</Text>
</TouchableOpacity>
<TouchableOpacity
style={GlobalStyles.smallButton}
onPress={() => {
this.props.navigation.navigate("UpdatePhoto");
}}
>
<Text style={GlobalStyles.buttonText}>UPDATE PHOTO</Text>
</TouchableOpacity>
</View>
<View style={GlobalStyles.container}>
<Text style={GlobalStyles.screenTitle}>My Posts</Text>
<View>
<FlatList
data={this.state.postList}
renderItem={({item}) => (
<View style={styles.container}>
<Text style={styles.postText}>
{item.text}
</Text>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.editPostButton}
onPress={() => {
setPostId(item.post_id);
this.props.navigation.navigate("MyPost");
}}
>
<Text style={styles.editButtonText}>EDIT</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.deletePostButton}
onPress={() => {
this.deletePost(item.post_id).then(() => {});
}}
>
<Text style={styles.deleteButtonText}>DELETE</Text>
</TouchableOpacity>
</View>
</View>
)}
keyExtractor={(item) => item.post_id.toString()}
/>
</View>
</View>
<TouchableOpacity
style={GlobalStyles.button}
onPress={() => {
this.props.navigation.navigate("Home");
}}
>
<Text style={GlobalStyles.buttonText}>HOME</Text>
</TouchableOpacity>
</View>
);
}
return (
<View>
<Text>Loading...</Text>
</View>
);
}
}
export default MyProfile;
Then finally the console error log.
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
at resolveDispatcher (react.development.js:1465:1)
at Object.useRef (react.development.js:1504:1)
at ExponentCamera.web.tsx:30:1
at renderWithHooks (react-dom.development.js:14985:1)
at updateForwardRef (react-dom.development.js:17044:1)
at beginWork (react-dom.development.js:19098:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:1)
at invokeGuardedCallback (react-dom.development.js:4056:1)
at beginWork$1 (react-dom.development.js:23964:1)
at performUnitOfWork (react-dom.development.js:22779:1)
at workLoopSync (react-dom.development.js:22707:1)
at renderRootSync (react-dom.development.js:22670:1)
at performSyncWorkOnRoot (react-dom.development.js:22293:1)
at react-dom.development.js:11327:1
at unstable_runWithPriority (scheduler.development.js:468:1)
at runWithPriority$1 (react-dom.development.js:11276:1)
at flushSyncCallbackQueueImpl (react-dom.development.js:11322:1)
at flushSyncCallbackQueue (react-dom.development.js:11309:1)
at scheduleUpdateOnFiber (react-dom.development.js:21893:1)
at Object.enqueueSetState (react-dom.development.js:12467:1)
at UpdatePhoto../node_modules/react/cjs/react.development.js.Component.setState (react.development.js:365:1)
at UpdatePhoto.componentDidMount$ (UpdatePhoto.js:18:1)
at tryCatch (runtime.js:63:1)
at Generator.invoke [as _invoke] (runtime.js:294:1)
at Generator.next (runtime.js:119:1)
at tryCatch (runtime.js:63:1)
at invoke (runtime.js:155:1)
at runtime.js:165:1
resolveDispatcher @ react.development.js:1465
useRef @ react.development.js:1504
(anonymous) @ ExponentCamera.web.tsx:30
renderWithHooks @ react-dom.development.js:14985
updateForwardRef @ react-dom.development.js:17044
beginWork @ react-dom.development.js:19098
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
beginWork$1 @ react-dom.development.js:23964
performUnitOfWork @ react-dom.development.js:22779
workLoopSync @ react-dom.development.js:22707
renderRootSync @ react-dom.development.js:22670
performSyncWorkOnRoot @ react-dom.development.js:22293
(anonymous) @ react-dom.development.js:11327
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
flushSyncCallbackQueueImpl @ react-dom.development.js:11322
flushSyncCallbackQueue @ react-dom.development.js:11309
scheduleUpdateOnFiber @ react-dom.development.js:21893
enqueueSetState @ react-dom.development.js:12467
./node_modules/react/cjs/react.development.js.Component.setState @ react.development.js:365
componentDidMount$ @ UpdatePhoto.js:18
tryCatch @ runtime.js:63
invoke @ runtime.js:294
(anonymous) @ runtime.js:119
tryCatch @ runtime.js:63
invoke @ runtime.js:155
(anonymous) @ runtime.js:165
Promise.then (async)
invoke @ runtime.js:164
(anonymous) @ runtime.js:190
callInvokeWithMethodAndArg @ runtime.js:189
enqueue @ runtime.js:212
(anonymous) @ runtime.js:119
./node_modules/regenerator-runtime/runtime.js.exports.async @ runtime.js:239
componentDidMount @ UpdatePhoto.js:16
commitLifeCycles @ react-dom.development.js:20663
commitLayoutEffects @ react-dom.development.js:23426
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
commitRootImpl @ react-dom.development.js:23151
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
commitRoot @ react-dom.development.js:22990
performSyncWorkOnRoot @ react-dom.development.js:22329
(anonymous) @ react-dom.development.js:11327
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
flushSyncCallbackQueueImpl @ react-dom.development.js:11322
flushSyncCallbackQueue @ react-dom.development.js:11309
discreteUpdates$1 @ react-dom.development.js:22420
discreteUpdates @ react-dom.development.js:3756
dispatchDiscreteEvent @ react-dom.development.js:5889
index.js:1
The above error occurred in the <ForwardRef> component:
at http://localhost:19006/static/js/bundle.js:22762:19
at Camera (http://localhost:19006/static/js/bundle.js:22195:81)
at div
at http://localhost:19006/static/js/bundle.js:136486:25
at UpdatePhoto (http://localhost:19006/static/js/bundle.js:160203:81)
at StaticContainer (http://localhost:19006/static/js/bundle.js:15316:16)
at EnsureSingleNavigator (http://localhost:19006/static/js/bundle.js:14997:23)
at SceneView (http://localhost:19006/static/js/bundle.js:15206:21)
at div
at http://localhost:19006/static/js/bundle.js:136486:25
at div
at http://localhost:19006/static/js/bundle.js:136486:25
at div
at http://localhost:19006/static/js/bundle.js:136486:25
at Background (http://localhost:19006/static/js/bundle.js:11554:20)
at Screen (http://localhost:19006/static/js/bundle.js:12732:107)
at div
at http://localhost:19006/static/js/bundle.js:136486:25
at div
at http://localhost:19006/static/js/bundle.js:136486:25
at NativeSafeAreaView (http://localhost:19006/static/js/bundle.js:129664:23)
at SafeAreaProvider (http://localhost:19006/static/js/bundle.js:129842:24)
at SafeAreaProviderCompat (http://localhost:19006/static/js/bundle.js:12675:23)
at NativeStackView (http://localhost:19006/static/js/bundle.js:11388:20)
at http://localhost:19006/static/js/bundle.js:16801:13
at NativeStackNavigator (http://localhost:19006/static/js/bundle.js:11323:31)
at EnsureSingleNavigator (http://localhost:19006/static/js/bundle.js:14997:23)
at BaseNavigationContainer (http://localhost:19006/static/js/bundle.js:14630:27)
at ThemeProvider (http://localhost:19006/static/js/bundle.js:13453:20)
at NavigationContainerInner (http://localhost:19006/static/js/bundle.js:13092:25)
at App (http://localhost:19006/static/js/bundle.js:5307:81)
at ExpoRootComponent (http://localhost:19006/static/js/bundle.js:27404:83)
at div
at http://localhost:19006/static/js/bundle.js:136486:25
at div
at http://localhost:19006/static/js/bundle.js:136486:25
at AppContainer (http://localhost:19006/static/js/bundle.js:130404:24)
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
console.<computed> @ index.js:1
error @ react-native-logs.fx.ts:34
logCapturedError @ react-dom.development.js:20085
update.callback @ react-dom.development.js:20118
callCallback @ react-dom.development.js:12318
commitUpdateQueue @ react-dom.development.js:12339
commitLifeCycles @ react-dom.development.js:20736
commitLayoutEffects @ react-dom.development.js:23426
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
commitRootImpl @ react-dom.development.js:23151
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
commitRoot @ react-dom.development.js:22990
performSyncWorkOnRoot @ react-dom.development.js:22329
(anonymous) @ react-dom.development.js:11327
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
flushSyncCallbackQueueImpl @ react-dom.development.js:11322
flushSyncCallbackQueue @ react-dom.development.js:11309
scheduleUpdateOnFiber @ react-dom.development.js:21893
enqueueSetState @ react-dom.development.js:12467
./node_modules/react/cjs/react.development.js.Component.setState @ react.development.js:365
componentDidMount$ @ UpdatePhoto.js:18
tryCatch @ runtime.js:63
invoke @ runtime.js:294
(anonymous) @ runtime.js:119
tryCatch @ runtime.js:63
invoke @ runtime.js:155
(anonymous) @ runtime.js:165
Promise.then (async)
invoke @ runtime.js:164
(anonymous) @ runtime.js:190
callInvokeWithMethodAndArg @ runtime.js:189
enqueue @ runtime.js:212
(anonymous) @ runtime.js:119
./node_modules/regenerator-runtime/runtime.js.exports.async @ runtime.js:239
componentDidMount @ UpdatePhoto.js:16
commitLifeCycles @ react-dom.development.js:20663
commitLayoutEffects @ react-dom.development.js:23426
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
commitRootImpl @ react-dom.development.js:23151
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
commitRoot @ react-dom.development.js:22990
performSyncWorkOnRoot @ react-dom.development.js:22329
(anonymous) @ react-dom.development.js:11327
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
flushSyncCallbackQueueImpl @ react-dom.development.js:11322
flushSyncCallbackQueue @ react-dom.development.js:11309
discreteUpdates$1 @ react-dom.development.js:22420
discreteUpdates @ react-dom.development.js:3756
dispatchDiscreteEvent @ react-dom.development.js:5889
react.development.js:1465
Uncaught (in promise) Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
at resolveDispatcher (react.development.js:1465:1)
at Object.useRef (react.development.js:1504:1)
at ExponentCamera.web.tsx:30:1
at renderWithHooks (react-dom.development.js:14985:1)
at updateForwardRef (react-dom.development.js:17044:1)
at beginWork (react-dom.development.js:19098:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:1)
at invokeGuardedCallback (react-dom.development.js:4056:1)
at beginWork$1 (react-dom.development.js:23964:1)
at performUnitOfWork (react-dom.development.js:22779:1)
at workLoopSync (react-dom.development.js:22707:1)
at renderRootSync (react-dom.development.js:22670:1)
at performSyncWorkOnRoot (react-dom.development.js:22293:1)
at react-dom.development.js:11327:1
at unstable_runWithPriority (scheduler.development.js:468:1)
at runWithPriority$1 (react-dom.development.js:11276:1)
at flushSyncCallbackQueueImpl (react-dom.development.js:11322:1)
at flushSyncCallbackQueue (react-dom.development.js:11309:1)
at scheduleUpdateOnFiber (react-dom.development.js:21893:1)
at Object.enqueueSetState (react-dom.development.js:12467:1)
at UpdatePhoto../node_modules/react/cjs/react.development.js.Component.setState (react.development.js:365:1)
at UpdatePhoto.componentDidMount$ (UpdatePhoto.js:18:1)
at tryCatch (runtime.js:63:1)
at Generator.invoke [as _invoke] (runtime.js:294:1)
at Generator.next (runtime.js:119:1)
at tryCatch (runtime.js:63:1)
at invoke (runtime.js:155:1)
at runtime.js:165:1
resolveDispatcher @ react.development.js:1465
useRef @ react.development.js:1504
(anonymous) @ ExponentCamera.web.tsx:30
renderWithHooks @ react-dom.development.js:14985
updateForwardRef @ react-dom.development.js:17044
beginWork @ react-dom.development.js:19098
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
beginWork$1 @ react-dom.development.js:23964
performUnitOfWork @ react-dom.development.js:22779
workLoopSync @ react-dom.development.js:22707
renderRootSync @ react-dom.development.js:22670
performSyncWorkOnRoot @ react-dom.development.js:22293
(anonymous) @ react-dom.development.js:11327
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
flushSyncCallbackQueueImpl @ react-dom.development.js:11322
flushSyncCallbackQueue @ react-dom.development.js:11309
scheduleUpdateOnFiber @ react-dom.development.js:21893
enqueueSetState @ react-dom.development.js:12467
./node_modules/react/cjs/react.development.js.Component.setState @ react.development.js:365
componentDidMount$ @ UpdatePhoto.js:18
tryCatch @ runtime.js:63
invoke @ runtime.js:294
(anonymous) @ runtime.js:119
tryCatch @ runtime.js:63
invoke @ runtime.js:155
(anonymous) @ runtime.js:165
Promise.then (async)
./node_modules/regenerator-runtime/runtime.js.exports.async @ runtime.js:239
componentDidMount @ UpdatePhoto.js:16
commitLifeCycles @ react-dom.development.js:20663
commitLayoutEffects @ react-dom.development.js:23426
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
commitRootImpl @ react-dom.development.js:23151
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
commitRoot @ react-dom.development.js:22990
performSyncWorkOnRoot @ react-dom.development.js:22329
(anonymous) @ react-dom.development.js:11327
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
flushSyncCallbackQueueImpl @ react-dom.development.js:11322
flushSyncCallbackQueue @ react-dom.development.js:11309
discreteUpdates$1 @ react-dom.development.js:22420
discreteUpdates @ react-dom.development.js:3756
dispatchDiscreteEvent @ react-dom.development.js:5889
VM30:2
Uncaught ReferenceError: process is not defined
at Object.4043 (<anonymous>:2:13168)
at r (<anonymous>:2:306599)
at Object.8048 (<anonymous>:2:9496)
at r (<anonymous>:2:306599)
at Object.8641 (<anonymous>:2:1379)
at r (<anonymous>:2:306599)
at <anonymous>:2:315627
at <anonymous>:2:324225
at <anonymous>:2:324229
at HTMLIFrameElement.e.onload (index.js:1:1)
4043 @ VM30:2
r @ VM30:2
8048 @ VM30:2
r @ VM30:2
8641 @ VM30:2
r @ VM30:2
(anonymous) @ VM30:2
(anonymous) @ VM30:2
(anonymous) @ VM30:2
e.onload @ index.js:1
be @ index.js:1
(anonymous) @ index.js:1
(anonymous) @ index.js:1
load (async)
be @ index.js:1
(anonymous) @ index.js:1
(anonymous) @ index.js:1
Promise.then (async)
(anonymous) @ index.js:1
(anonymous) @ index.js:1
t @ index.js:1
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
beginWork$1 @ react-dom.development.js:23964
performUnitOfWork @ react-dom.development.js:22779
workLoopSync @ react-dom.development.js:22707
renderRootSync @ react-dom.development.js:22670
performSyncWorkOnRoot @ react-dom.development.js:22293
(anonymous) @ react-dom.development.js:11327
unstable_runWithPriority @ scheduler.development.js:468
runWithPriority$1 @ react-dom.development.js:11276
flushSyncCallbackQueueImpl @ react-dom.development.js:11322
flushSyncCallbackQueue @ react-dom.development.js:11309
scheduleUpdateOnFiber @ react-dom.development.js:21893
enqueueSetState @ react-dom.development.js:12467
./node_modules/react/cjs/react.development.js.Component.setState @ react.development.js:365
componentDidMount$ @ UpdatePhoto.js:18
tryCatch @ runtime.js:63
invoke @ runtime.js:294
(anonymous) @ runtime.js:119
tryCatch @ runtime.js:63
invoke @ runtime.js:155
(anonymous) @ runtime.js:165
Solution 1:[1]
There seems to be something strange going on with peer dependencies. Try to delete
rm -rf node_modules/expo-camera/node_modules/react if this solves it for you.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | FibHeap |
