import { StyleSheet, Text, View } from 'react-native'
import * as firebase from 'firebase';
//firebaseinititalized//
const[message,setMessage]=useState('');
const [messages, setMessages] = useState([])
useEffect(() => {
firebase.database.ref().child('messages').once('value',
snapshot=>{
const data=snapshot.val()
if(snapshot.val()){
const initMessages=[];
Object.
keys(data).
forEach(message=>initMessages.push(data[message]));
(initMessages)=>setMessages([initMessages]);
}
}
)
firebase.database.ref().child('messages').on("child_added",
snapshot=>{
const data=snapshot.val()
if(snapshot.val()){
(prevMessages)=> setMessages([data,...prevMessages]);
}
}
)
}, [])
const addItem =()=>{
if(!message) return;
const newMessage=firebase.database.ref().child().push();
newMessage.set(message,()=>setMessage(''));
}
function Hookfire() {
return (
<View >
<View >
<TextInput placeholder=" enter text message"
value={message} onChangeText={text=>setMessage(text)}/>
<Button title="send" onPress={addItem}/>
</View>
<FlatList data={messages}
renderItem={({item})=>
<View >
<Text >{item}</Text>
</View>}
/>
</View>
)
}
export default Hookfire
const styles = StyleSheet.create({})
error message shows that:
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
you have move the hook call inside the HookFire function.
import { StyleSheet, Text, View } from 'react-native'
import * as firebase from 'firebase';
function Hookfire() {
const[message,setMessage]=useState('');
const [messages, setMessages] = useState([])
useEffect(() => {
firebase.database.ref().child('messages').once('value',
snapshot=>{
const data=snapshot.val()
if(snapshot.val()){
const initMessages=[];
Object.
keys(data).
forEach(message=>initMessages.push(data[message]));
(initMessages)=>setMessages([initMessages]);
}
}
)
firebase.database.ref().child('messages').on("child_added",
snapshot=>{
const data=snapshot.val()
if(snapshot.val()){
(prevMessages)=> setMessages([data,...prevMessages]);
}
}
)
}, [])
const addItem =()=>{
if(!message) return;
const newMessage=firebase.database.ref().child().push();
newMessage.set(message,()=>setMessage(''));
}
return (
<View >
<View >
<TextInput placeholder=" enter text message"
value={message} onChangeText={text=>setMessage(text)}/>
<Button title="send" onPress={addItem}/>
</View>
<FlatList data={messages}
renderItem={({item})=>
<View >
<Text >{item}</Text>
</View>}
/>
</View>
)
}
export default Hookfire;
Related
I'm making a react native app on Expo, but the whole app crashes everytime I try to get into this one page. This is my first time using react native, and I'm still a beginner to react, but I can't see what's causing the issue. The error I'm getting is Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it., but I can't see where
import { StyleSheet, Text, View, TouchableOpacity, ScrollView, TextInput } from 'react-native'
import React, { useState, useEffect } from 'react'
// import CartCard from '../Components/CartCard'
import ItemCard from '../Components/ItemCard'
const Cart = ({navigation}) => {
const [details, setDetails] = useState([])
useEffect(()=>{
getData()
}, [])
const getData = async() => {
try {
const getValues = await AsyncStorage.getItem('object')
if(getValues !== null){
console.log(JSON.parse(getValues))
setDetails(getValues)
// const objectValues = JSON.parse(getValues)
// setDetails(objectValues)
// getValues.forEach(object => {
// console.log("id:", object.id)
// setToyId(object.id)
// })
}
}catch(error){
console.log('getData didnt work')
}
}
const [cardholder, setCardholder] = useState('');
const [cardNumber, setCardNumber] = useState('');
const [expiryDate, setExpiryDate] = useState('');
const [cvc, setCvc] = useState('');
const [allItems, setAllItems] = useState(0);
const [total, setTotal] = useState(0)
const clearCart = () => {
console.log('cc')
}
const countAllItems = () => {
console.log('cai')
}
const countTotal = () => {
console.log('ct')
}
return (
<ScrollView style={{backgroundColor: 'white', height: '100%'}}>
<ItemCard />
<View>
<View style={styles.payment}>
<Text>Your Shopping Cart</Text>
<View>
<Text value={allItems} onChangeText={(value)=>{setAllItems(value)}}>Overall Items: {countAllItems}</Text>
<Text value={total} onChangeText={(value)=>{setTotal(value)}}>Total Price: ${countTotal}.00</Text>
</View>
</View>
<Text>Payment</Text>
<TextInput placeholder='Cardholder Name' style={styles.inputsLong} placeholderTextColor='black' value={cardholder} onChangeText={(value)=>setCardholder(value)}/>
<TextInput placeholder='Card Number' style={styles.inputsLong} placeholderTextColor='black' value={cardNumber} onChangeText={(value)=>setCardNumber(value)}/>
<View style={styles.shortForm}>
<TextInput placeholder='MM/YY' style={styles.inputsShort} placeholderTextColor='black' value={expiryDate} onChangeText={(value)=>setExpiryDate(value)} />
<TextInput placeholder='CVC' style={styles.inputsShort} placeholderTextColor='black' value={cvc} onChangeText={(value)=>setCvc(value)}/>
</View>
<View style={styles.buttonRow}>
<TouchableOpacity>
<Text style={styles.cancelButton} onPress={clearCart}>Cancel Order</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.orderButton} onPress={()=>navigation.navigate('ConfirmScreen')}>Place Order</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>
)
}
export default Cart
const styles = StyleSheet.create({ // styles })
ItemCard component doesn't take any parameters yet because I'm having problems storing data and passing data between pages, but this is what the component looks like in its current state:
import { StyleSheet, Text, View, ScrollView } from 'react-native'
import React from 'react'
const ItemCard = () => {
return (
<ScrollView>
<View style={styles.itemSection}>
<View style={styles.card}></View>
</View>
</ScrollView>
)
}
export default ItemCard
const styles = StyleSheet.create({ // styles })
For this warning
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
you have to call the functions
eg. countTotal()
<Text value={total} onChangeText={(value)=>{setTotal(value)}}>Total Price: ${countTotal()}.00</Text>
if you are using onPress then like this
<Text style={styles.cancelButton} onPress={()=>clearCart()}>Cancel Order</Text>
I've been trying to replace a view in React Native, but to no success. The app closes without errors whenever I try <TouchableOpacity onPress={() => {handleChangeMyView();}}> :
What am I doing wrong? How can I make it work?
Thank you all in advance.
import React, {
useState
} from 'react';
import {
SafeAreaView,
View,
TouchableOpacity,
} from 'react-native';
import MyInitialView from './MyInitialView';
const SiteContainer = () => {
let MyDynamicView = () => {
return (
<View></View>
);
};
const [MyDynamicViewArea, setMyDynamicViewArea] = useState(MyInitialView);
const handleChangeMyView = () => {
setMyDynamicViewArea(MyDynamicView);
};
return (
<SafeAreaView>
{MyDynamicViewArea}
<TouchableOpacity onPress={() => {handleChangeMyView();}}>
<View>
<FontAwesome name="quote-left"></FontAwesome>
</View>
</TouchableOpacity>
</SafeAreaView>
);
};
export default SiteContainer;
MyInitialView :
import React from 'react';
import {
View
} from 'react-native';
export default function MyInitialView() {
return (
<View></View>
);
}
You can use boolean value for viewing MyInitialView using useState
const [toViewMyInitialView, setToViewMyInitialView] = useState(false);
and in handleChangeMyView function set the above value as true
const handleChangeMyView = () => {
setToViewMyInitialView(true);
};
And in the SiteContainer
<SafeAreaView style={styles.siteContainer}>
// here I don't know a way to display a component in react-native, so
// you need to display the component MyInitialView if the
// toViewMyInitialView is true and when toViewMyInitialView id false it
// display MyDynamicViewArea
{toViewMyInitialView && <MyInitialView/>}
{!toViewMyInitialView && <MyDynamicViewArea/>}
<TouchableOpacity onPress={() => {handleChangeMyView()}}>
<View>
<FontAwesome name="quote-left"></FontAwesome>
</View>
</TouchableOpacity>
</SafeAreaView>
For example, in react-native, I can pass a ref to a regular TextInput and then, through this ref, call the methods:
const inputRef = useRef(null);
const myCallback = () => {
inputRef?.current?.focus();
}
<>
<TouchableOpacity onPress={() => myCallback()}>
<Text>
Press here to focus the input!
</Text>
</TouchableOpacity>
<TextInput
ref={inputRef}
{...props} // Doesn't matter, nothing special
>
</>
So, my question is, how can I create methods on my components, so I can call them from outside of component using ref.
Of course, I'm interested in creating a method in a functional component.
You can use useImperativeHandle hook to expose the methods you need to have with the input element.
Try like this.
import React, { useImperativeHandle, forwardRef, useRef } from "react";
import { Button, StyleSheet, View, TextInput } from "react-native";
const MyTextInput = (props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
doFocus: () => {
inputRef.current.focus();
},
doBlur: () => {
inputRef.current.blur();
}
}));
return <TextInput ref={inputRef} style={props.style} />;
};
const MyCustomTextInput = forwardRef(MyTextInput);
const App = () => {
const myInputRef = useRef();
return (
<View style={styles.app}>
<MyCustomTextInput ref={myInputRef} style={styles.input} />
<View style={styles.button}>
<Button
onPress={() => {
myInputRef?.current?.doFocus();
}}
title="focus"
style={styles.button}
/>
</View>
<View style={styles.button}>
<Button
onPress={() => {
myInputRef?.current?.doBlur();
}}
title="blur"
style={styles.button}
/>
</View>
</View>
);
};
Code sandbox => https://codesandbox.io/s/react-native-web-forked-mnwee?file=/src/App.js
I have no errors showing but I am getting a blank page when my app runs. It started rendering a blank page when started putting some api code which I copied and pasted from another project where it worked exactly perfect but for some reason, it is refusing to work here This is how my code looks like. This is my App.js file
import React from 'react'
import { StyleSheet, Text, View } from 'react-native'
import Screen from './app/components/Screen'
import ProductScreen from './app/screens/ProductScreen';
export default function App() {
return (
<Screen>
<ProductScreen />
</Screen>
)
}
Then this is the product screen.js
import React, {useState, useEffect} from 'react'
import { FlatList, StyleSheet, ActivityIndicator, Text, View } from 'react-native'
import Card from '../components/Card';
export default function ProductScreen() {
const [products, setproducts] = useState([]);
const [loading, setloading] = useState(true);
const getProducts = async () => {
try {
const response = await fetch('https://fakestoreapi.com/products/1');
const data = await response.json();
setproducts(data);
} catch (error) {
console.log("Something went wrong in your code",error)
} finally {
setloading(false);
}
}
useEffect(() => {
getProducts();
}, []);
return (
<View>
{loading ? <ActivityIndicator/> : (
<FlatList
data={products}
keyExtractor={(id) => id}
renderItem={({item}) => (
<Card
title={item.title}
subtitle={item.description}
img={item.image}
/>
)}
/>
)}
</View>
)
}
const styles = StyleSheet.create({})
And lastly the card.js file
import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
import AppText from './AppText';
export default function Card({title, subtitle, img}) {
return (
<View style={styles.container}>
<Image source={img} style={styles.image} />
<View style={styles.cardText}>
<AppText style={{color: "black"}}>{title}</AppText>
<AppText style={{color: "#4ecdc4"}}>{subtitle}</AppText>
</View>
</View>
)
}
Where could I be going wrong?
Well there are several issues in your Expo Snack. First your expression of:
{loading && <FlatList />}
is wrong because you're setting it to check for loading of true when after you retrieve your data in getProducts you set it to false.
Was able to get it to work, again, with:
import React, { useState, useEffect } from 'react'
import { FlatList, StyleSheet, View } from 'react-native'
import Card from '../components/Card'
export default function ProductScreen() {
const [products, setProducts] = useState([])
const [loading, setLoading] = useState(true)
const getProducts = async () => {
try {
const response = await fetch('https://fakestoreapi.com/products/5')
const data = await response.json()
setProducts([data])
setLoading(false)
} catch (error) {
console.log('Something went wrong in your code', error)
}
}
useEffect(() => {
getProducts()
}, [])
return (
<View style={styles.container}>
{!loading && products.length !== 0 && (
<View>
<FlatList
data={products}
keyExtractor={(_, id) => id.toString()}
renderItem={({ item }) => <Card title={item.title} subtitle={item.description} img={item.image} />}
/>
</View>
)}
</View>
)
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'lightgrey',
flex: 1,
},
})
Another error exists in Card for Image. Per memory when passing an image URL it should be set with a URI:
<Image source={{ uri: img }} style={styles.image} />
Another issue you'll face is in ProductScreen the View style for container should have a flex: 1 applied as indicated in the code above.
Looking at the code for snack.expo.dev/#vuyi/spontaneous-candy it seems your missing the conditional rendering in your return for the ProductScreen.
Your code looks like this:
<View style={styles.container}>
{loading &&
<FlatList
data={[products]}
keyExtractor={(_, id) => id.toString()}
renderItem={({item}) =>
<Card
title={item.title}
subtitle={item.description}
img={item.image}
/>
}
/>
}
</View>
When it needs to look something like this:
<View style={styles.container}>
{loading ? null :
<FlatList
data={[products]}
keyExtractor={(_, id) => id.toString()}
renderItem={({item}) =>
<Card
title={item.title}
subtitle={item.description}
img={item.image}
/>
}
/>
}
</View>
Adding that conditional will prevent your Flatlist component from rendering before it has access to the data you are fetching. It looks like you had it right in the original post but not in the Expo Snack environment.
I am trying to run a react-native-web project, when I try running it, I get the following error
When I stacktraced I found my error is exactly happening in the following code
import React, {useState, useEffect} from 'react';
import {
SafeAreaView,
KeyboardAvoidingView,
TextInput,
View,
Text,
Image,
Button,
TouchableOpacity,
} from 'react-native';
import qs from 'qs';
import {Images} from '../../assets';
import {API} from '../../api';
import {disabledColor, successColor} from '../../config/colors';
export default function LoginScreenWeb(props) {
const {navigation} = props;
const [firstName, setFirstName] = useState('');
const [mobile, setMobile] = useState('');
const [width, getWidth] = useState(null);
const SetWidth = () => {
getWidth(window.screen.availWidth);
};
// useEffect(() => {
// // SetWidth();
// // setInterval(SetWidth, 1000);
// }, []);
// const onHandlePress = () => {
// async function post() {
// try {
// const response = await API.postFormData(
// `/users/signup`,
// qs.stringify({
// firstName,
// mobile,
// }),
// );
// navigation.navigate('otp');
// localStorage.setItem('mobile', mobile);
// console.log('loginRes--', response);
// } catch (e) {
// console.log(e);
// }
// }
// post();
// };
return (
<SafeAreaView style={styles.container}>
<View
// style={
// width > 414 ? styles.inner_container_web : styles.inner_container_mob
// }
>
<Image
source={Images.login_web}
// style={width > 414 ? styles.image_web : styles.image_mob}
/>
<KeyboardAvoidingView>
<View style={{padding: 16}}>
<Text style={styles.textLabel}>Name</Text>
<TextInput
placeholder="Enter your name"
style={styles.textInput}
// value={firstName}
// onChangeText={(firstName) =>
// setFirstName(firstName.replace(/[^A-Za-z]/g, ''))
// }
/>
<Text style={styles.textLabel}>+91</Text>
<TextInput
placeholder="Enter your phone number"
style={styles.textInput}
maxLength={10}
keyboardType="number-pad"
// value={mobile}
// onChangeText={(mobile) =>
// setMobile(mobile.replace(/[^0-9]/g, ''))
// }
/>
<View style={{alignItems: 'center'}}>
{/* {firstName && mobile.length === 10 ? ( */}
<TouchableOpacity
// onPress={() => onHandlePress()}
style={styles.enable_continue}>
<Text style={styles.continue}>Continue</Text>
</TouchableOpacity>
{/* ) : ( */}
<TouchableOpacity style={styles.disble_continue}>
<Text style={styles.continue}>Continue</Text>
</TouchableOpacity>
{/* )} */}
</View>
<View style={{flexDirection: 'row'}}>
<View style={styles.cookies} />
<Text style={{fontSize: '12px'}}>
By continuing you agree to the Terms of Service and Privacy
policy
</Text>
</View>
</View>
</KeyboardAvoidingView>
</View>
</SafeAreaView>
);
}
As soon as I uncomment the useeffect part I get the Hooks can only be called inside the body of a function component. error however I am using a functional component here.
Am unable to figure how to fix the error, could anyone help me out here, thanks in advance, let me know if anything else is required for clarity
Stacktrace ->
try this too :
const LoginScreenWeb= (props) => {//////another code}
export default LoginScreenWeb
Also check the version(react) you are working with..
React Hooks are available in React 16.8
This was an error of npm link and version mismatch, once I linked my react package the error got fixed