I have a component like below based on Hooks
import React, { useEffect, useState } from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Animated
} from 'react-native';
import CAStyles from '../res/CAStyles';
const CACard = (props ) => (
<TouchableOpacity onPress={props.cardTouched}>
<View style={[styles.cardContainer, CAStyles.ALIGN_CENTER]} width={props.width} height={props.height}>
<Text style={styles.textStyle}>{props.title}</Text>
</View>
</TouchableOpacity>
);
export default CACard
I'd like to have own state values and functions inside the hook. But it is throwing syntax error. I know it is possible with Class based components but not sure why it is not possible with Hooks.
My subsequent attempts to find a solution is futile. Can someone help me out here. Thanks in advance.
Thanks to #JMadelaine for pointing it out. I changed as below and it all works fine.
const CACard = (props ) => {
return (
<TouchableOpacity onPress={props.cardTouched}>
<View style={[styles.cardContainer, CAStyles.ALIGN_CENTER]} width={props.width} height={props.height}>
<Text style={styles.textStyle}>{props.title}</Text>
</View>
</TouchableOpacity>
)
};
As JMadelaine correctly pointed out. You need to write useState inside functional component definition. Restructure your code like this:
import React, { useEffect, useState } from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Animated
} from 'react-native';
import CAStyles from '../res/CAStyles';
const CACard = (props) =>{
const [aStateVar, setAStateVar] = useState(false);
return (
<TouchableOpacity onPress={props.cardTouched}>
<View style={[styles.cardContainer, CAStyles.ALIGN_CENTER]} width={props.width} height={props.height}>
<Text style={styles.textStyle}>{props.title}</Text>
</View>
</TouchableOpacity>
);
};
export default CACard;
Related
Styles are not showing in React Native. I'm new to RN so please if you can help me understand ..Here is the code :
import { template } from '#babel/core'
import React from 'react'
import { View , Text, SafeAreaView, StyleSheet } from 'react-native'
const styles = StyleSheet.create({
container : {
alignItems:'center',
backgroundColor:'pink',
},
})
const App = ()=>{
return(
<SafeAreaView>
<View style={styles.container}>
<Text>Hello World!!</Text>
</View>
</SafeAreaView>
)
}
export default App
So, I found the answer after half an hour. It's just i needed to rerun the application and it worked. Also flex :1 helps.
I am developing mobile app using React Native expo.. I am getting the following exception:
Invalid hook call. Hooks can only be called inside the body of a function component....
I have gone through the other answers posted here on SO and have confirmed that the hook in my code is indeed inside a function. But still I am unable to resolve the error. KIndly help. Please see my code below. Let me know if more clarification is needed.
import React, { useState, useEffect } from 'react';
import { SafeAreaView, StatusBar, Button, View, Platform , Text} from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import Constants from 'expo-constants';
const statusBarPadding = Platform.OS === 'android' ? StatusBar.currentHeight: 0;
export default function OpenGallery () {
const [image, setImage] = useState(null);
useEffect(() => { // hook is inside function but still getting error
(async () => {
if (Platform.OS !== 'web') {
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
alert('Sorry, we need camera roll permissions to make this work!');
}
}
})();
}, []);
return (
<SafeAreaView style={{ paddingTop: statusBarPadding }}>
<Text> Some text </Text>
</SafeAreaView>
);
}
Second file:
import React from 'react';
import { SafeAreaView, StatusBar, Button, View, Platform , Text} from 'react-native';
import OpenGallery from './OpenGallery'
const statusBarPadding = Platform.OS === 'android' ? StatusBar.currentHeight: 0;
export default function CameraScreen() {
return (
<SafeAreaView style={{ paddingTop: statusBarPadding }}>
<Text> Upload image from gallery.</Text>
<Button title="Select from Gallery" onPress={OpenGallery} />
</SafeAreaView>
);
}
it is in fact not being called from inside the component. you are calling it from the JSX, which is entirely different. there are two issues here that break the rules of hooks.
hooks must be called unconditionally. you are breaking that rule here.
<Button title="Select from Gallery" **onPress={OpenGallery}** />
Hooks must be called from inside a functional component. you cannot import another component and call it as a function. this is what you're doing. you are calling the react component on a onPress method which is wrong.
What can you do to fix it?
bring the state down. make the check to see if it's on a web or a mobile in the second file itself. i would post the code but i don't have expo installed at the moment.
It might sound out of scope here but I think in your case, you need to specify the behaviour on how do you want the OpenGallery to appear after pressing the button on CameraScreen... you may be using navigation (may be react-navigation) or using a modal.
Let's say you're using react-navigation. (as you're using expo, it's normally included in the project) https://reactnavigation.org/
On CameraScreen
export default function CameraScreen({navigation}) {
const gotoOpenGallery = () => {
navigation.navigate('OpenGallery');
}
return (
<SafeAreaView style={{ paddingTop: statusBarPadding }}>
<Text> Upload image from gallery.</Text>
<Button title="Select from Gallery" onPress={gotoOpenGallery} />
</SafeAreaView>
);
}
You will also need to create a StackNavigator
Your App.js (or your entry point of the app)
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import OpenGallery from './OpenGallery';
import CameraScreen from './CameraScreen';
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="CameraScreen" component={CameraScreen} />
<Stack.Screen name="OpenGallery" component={OpenGallery} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
I'm super new to react native & having a hard time connecting separate files with my App.js. I've got a user-defined component in a separate file. This is what I've right now in the app.js
import React from 'react';
import TextImg from "./components/comp";
import { StyleSheet, Text, View, Image } from 'react-native';
export default function App() {
return (
<View style={{alignItems:'center', top:150}}>
<Image source={require('./images/pic.jpeg')} style={{ width: 290, height: 190 }}/>
<TextImg text='Mt. Fuji'/>
<TextImg source={{imageUri: 'https://reactjs.org/logo-og.png'}} style={{width: 400, height: 400}} />
</View> );
};
I am importing components from comp.js, and this is what I've in the comp.js file
import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
function TextImg(textprop, imgprop) {
return (
<React.Fragment>
<Text>{textprop.text}</Text>
<Image source={imgprop.imageUri}></Image>
</React.Fragment>
);
};
But this only shows the text, but not the image. Can anyone help with this?
Thanks in advance for help!
All your props would be passed as a single parameter. So you should change your component like below.
import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
export default function TextImg(props) {
return (
<React.Fragment>
<Text>{props.text}</Text>
<Image source={props.imageUri} style={props.style}></Image>
</React.Fragment>
);
};
You will have to import it in your app.js. (Assuming your file name is TextImg.js and its in the same path)
import TextImg from './TextImg'
You are not passing your props correctly.
Here is a revamp of your code, but in the proper way:
import React from 'react';
import { TextImg } from "./components/comp";
import { StyleSheet, Text, View, Image } from 'react-native';
export default function App() {
return (
<View style={{alignItems:'center', top:150}}>
<Image source={require('./images/pic.jpeg')} style={{ width: 290, height: 190 }}/>
<TextImg text='Mt. Fuji' imageUri: {'https://reactjs.org/logo-og.png'} />
</View> );
};
Then in comp.js
import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
export const TextImg = ({ text, imageUri }) => {
return (
<React.Fragment>
<Text>{text}</Text>
<Image source={imageUri} style={{width: 400, height: 400}} />
</React.Fragment>
);
};
This will fix it up for you. Study the code and try to understand what was done. But I'll also advise you to learn about React props.
I am making a react app using expo and I want to allow children in my TopicSection element. I followed this guide for allowing children in JSX elements and wrote the below code. I have tried using this.props.children but either way it gives me "TypeError: undefined is not an object (evaluating 'props.children')"
import * as React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import * as WebBrowser from 'expo-web-browser';
import { RectButton, ScrollView } from 'react-native-gesture-handler';
export default function TopicsScreen() {
return (
<ScrollView style={styles.container} contentContainerStyle={styles.contentContainer}>
<TopicSection
icon="ios-chatboxes"
text="Introduction">
<Text>This is where I want to put elements</Text>
</TopicSection>
</ScrollView>
);
}
function TopicSection({icon, text, props}) {
return (
<View style={styles.TopicSection}>
<View style={styles.TopicSectionContainer && {flexDirection: 'row'}}>
<Ionicons name={icon} size={32} color="rgba(0,0,0,0.35)" />
<Text style={styles.TopicSectionText}>{" " + text}</Text>
</View>
{props.children}
</View>
);
}
You’re destructuring the props object in TopicSection, so by doing ({icon, text, props}), you’re implying there is a prop called props, which there isn’t.
You either need to destructure out children and use it directly, or do ...props, which assigns all the remaining, unspecified props to props.
I use reactnavigation and I am hiding the statusbar at the top, but it leaves an empty space above the header.
I already tried paddingTop or marginTop, but none work.
This is how I hide the statusbar.
import React from 'react';
import { Platform, View, StatusBar } from 'react-native';
import { Tabs, Drawer } from './config/router';
const App = () => (
<View style={{flex:1}}>
<StatusBar hidden={true} />
<Drawer />
</View>
);
export default App;
Any idea would be helpful.
Thanks.
How to Fix it
I add the following to the index.js:
import React from 'react';
import { Platform, View, StatusBar } from 'react-native';
import { Tabs, Drawer } from './config/router';
import { SafeAreaView } from 'react-navigation';
SafeAreaView.setStatusBarHeight(0);
const App = () => (
<View style={{flex:1}}>
<StatusBar hidden={true} />
<Drawer />
</View>
);
export default App;
Basically added the SafeAreaView part.
Hope this is helpful for others.
Try the static function Status Bar. You might need to convert the component to a React Component/Pure Component. Try it with and without converting it.
componentDidMount(){
StatusBar.setHidden(true,true);
}