React Native not recognizing useState hook - javascript

Render Error:
(0,_reactNative.usestate) is not a function.(In'(0,_reactNative.useState)(''),'(0,_reactNative.useState)'is undefined
This is the error my code is producing. All the imports are up to date. Not sure why it is not recognizing useState.
import React from 'react';
import { View, StyleSheet,TextInput,useEffect,useState } from 'react-native';
import db from 'D:/App development/PRLog/PrLogBeta/database/firestore'
const EnteryModal = props => {
const [numReps,setNumReps] = useState('');
useEffect(() => {
db.collection('Bench').add({reps:{newNum}})
},[]).then(() => {
console.log('Number Added!');
});
return(
<View style={styles.inputStyle}>
<form>
<TextInput
style = {styles.inputStyle}
keyboardType='number-pad'
placeholder={props.RepsOrWeight}
placeholderTextColor = 'white'
textAlign='center'
onChangeText={newNum => setNumReps(newNum)}
defaultValue={numReps}
onSubmitEditing={useEffect(() => {
db.collection('Bench').add({reps:{newNum}})
},[]).then(() => {
console.log('Number Added!');
})}
>
</TextInput>
</form>
</View>
);
};

You need to import useState and useEffect from React, not React Native
You cannot call .then() on useEffect since it does not return a promise.
You can't use useEffect as a callback function.
EDIT: Code example:
Based on the snippet from your question, it seems like you're trying to trigger a POST request to your database on submitting the text input. This can be achieved without useEffect by simply passing a handler function to your text input like so.
import React, { useEffect, useState } from 'react';
import { View, StyleSheet,TextInput } from 'react-native';
import db from 'D:/App development/PRLog/PrLogBeta/database/firestore'
const EnteryModal = props => {
const [numReps,setNumReps] = useState('');
const handleSubmit = async () => {
try {
await db.collection('Bench').add({reps:{newNum}});
console.log('Number Added!');
} catch (error) {
console.log(error)
}
}
return(
<View style={styles.inputStyle}>
<form>
<TextInput
style = {styles.inputStyle}
keyboardType='number-pad'
placeholder={props.RepsOrWeight}
placeholderTextColor = 'white'
textAlign='center'
onChangeText={newNum => setNumReps(newNum)}
defaultValue={numReps}
onSubmitEditing={handleSubmit}
>
</TextInput>
</form>
</View>
);
};

Use useState and useEffect as a react component not as react native component.
as shown in below example.
import React, { useEffect, useState } from 'react';
import { View, StyleSheet, TextInput} from 'react-native';
import db from 'D:/App development/PRLog/PrLogBeta/database/firestore'
const EnteryModal = props => {
const [numReps, setNumReps] = useState('');
useEffect(() => {
dataBaseCollection();
console.log("Number Added!");
}, []);
const dataBaseCollection = () => {
db.collection('Bench').add({ reps: { newNum } });
}
return (
<View style={styles.inputStyle}>
<form>
<TextInput
style={styles.inputStyle}
keyboardType='number-pad'
placeholder={props.RepsOrWeight}
placeholderTextColor='white'
textAlign='center'
onChangeText={newNum => setNumReps(newNum)}
defaultValue={numReps}
onSubmitEditing={(event) => {
dataBaseCollection();
}}
>
</TextInput>
</form>
</View>
);
};

Related

How to call a function from another .js file in React Native Expo

I'm new to React and I've faced such a problem:
I have Main.js file with a button:
import * as React from 'react';
import { StyleSheet, Text, View, SafeAreaView, Pressable, Alert } from 'react-native';
import { MaterialIcons, MaterialCommunityIcons} from '#expo/vector-icons';
import { DrawerActions } from '#react-navigation/native';
import Scanner from './Scanner'
export default function Main({ navigation }) {
return (
....
<View style={styles.container}>
<Pressable style={styles.button} onPress={ <Scanner() function call> }>
<Text style={styles.buttonText}>Take charger</Text>
</Pressable>
</View>
);
}
An I have another file Scanner.js:
import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
export default function Scanner() {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
alert(`Bar code with type ${type} and data ${data} has been scanned!`);
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={styles.container}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
/>
{scanned && <Button title={'Tap to Scan Again'} onPress={() => setScanned(false)} />}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
}
});
How can I call a function Scanner() from Scanner.js on button click in the Main()
function in Main.js. I've tried onPress={() => Scanner} but it didn't work for me because of wrong hooks usage.
You should write function Scan in the parent component -> Main.js and forward it to the children component -> Scanner.js. That's called prop drilling
https://blogs.perficient.com/2021/12/03/understanding-react-context-and-property-prop-drilling/#:~:text=Prop%20drilling%20refers%20to%20the,because%20of%20its%20repetitive%20code.
This is not a good patern, but you can do that. You can create the function in the parent and send it as a prop to the child or you can use context hook from react, that hook lets you pass the function from the child to the parent. Another method is to use forwardRef, this will let you call the child function from the parent.

React Native Flatlist rendered all items only for a millisecond

I get my data from firebase, push the data into an array and render the items in flatlist component. What did i miss?
but list render the items only for a really short time.
import React, { useState, useEffect } from 'react';
import { FlatList, Box } from "native-base";
import { StyleSheet } from 'react-native'
import EventCard from "./EventCard.js";
import { LogBox } from 'react-native';
import { ActivityIndicator } from 'react-native';
import { getFirestore, collection, getDocs } from 'firebase/firestore';
// Silent warning about https://github.com/facebook/react-native/issues/12981
LogBox.ignoreLogs(['Setting a timer']);
export default function Events() {
const [loading, setLoading] = useState(true);
const [events, setEvents] = useState({});
useEffect(() => {
let eventData = []
const firestore = getFirestore();
const querySnapshot = getDocs(collection(firestore, 'events'));
querySnapshot.then(querySnapshot => {
querySnapshot.docs.map(doc => {
eventData.push(doc.data())
setEvents(eventData)
})
});
setLoading(false);
}, []);
if (loading) {
return <ActivityIndicator />;
}
return (
<Box style={styles.container}>
<FlatList
data={events}
keyExtractor={item => item.key}
renderItem={({ item }) => (<EventCard key={Date.now()} eventData={item} />
)}
/>
</Box>
);
}
const styles = StyleSheet.create({
container: {
alignSelf: 'stretch',
alignItems: 'center'
},
})
Thanks for your time. i really stuck.
You have setEvents(eventData) in the map() so after every iteration the state is being updated. Instead parse the data and then update state once.
querySnapshot.then(querySnapshot => {
querySnapshot.docs.map(doc => {
eventData.push(doc.data())
})
// After iterating over all docs
setEvents(eventData)
});

ReactNative Context returns undefined when trying to access a value

I am trying to use the values/functions from my context but every time I console.log a value that Coes from context the value is undefined.
This is my Context:
import { NativeStackNavigationProp } from '#react-navigation/native-stack';
import React, {createContext, FC, useEffect } from 'react';
import { useState } from 'react';
import {fbInit, setNewUserFireStore, subscribeUserFS } from '../services/FirebaseServices';
const initialState = {
signedIn: false,
}
export const FirebaseContext = createContext();
export const FirebaseContextProvider = ({children}) => {
const [isUserSignedIn, setIsUserSignedIn] = useState(initialState.signedIn);
useEffect(() => {
fbInit();
})
const testLog = () => {
console.log("TAG Test Log Func")
}
return (
<FirebaseContext.Provider value={{isUserSignedIn, setIsUserSignedIn}}>
{children}
</FirebaseContext.Provider>
);
}
This is where I am trying to use the values (I am trying to log the values when I press the Button)
import { useNavigation } from '#react-navigation/native';
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import {Button, Card, TextInput} from 'react-native-paper';
import { FirebaseContext } from '../../context/FirebaseContext';
import React, {useContext, useEffect, useState } from 'react';
const initialUserState = {
userName: 'Nicole Lopez',
password: '1001008888',
}
export default function LoginScreen() {
const [disabled, setDisabled] = useState(false);
const [userState, setUserState] = useState(initialUserState);
const { fbContext } = useContext(FirebaseContext);
const navigation = useNavigation();
const onInputChange = (field, value) => {
setUserState({
...userState,
[field]: value
})
}
useEffect(() => {
setDisabled(userState.userName.length === 0 || userState.password.length === 0);
}, [userState.userName, userState.password])
return (
<View style={styles.container}>
<Card style={styles.card}>
<TextInput
mode="outlined"
label="Förnamn & Efternman"
defaultValue={userState.userName}
onChangeText={text => onInputChange("username", text)}
right={<TextInput.Icon name="account" onPress={() => {
}}/>}
style={styles.textInput}/>
<TextInput
mode="outlined"
label="Anställningsnummer 100100xxxx"
defaultValue={userState.password}
right={<TextInput.Icon name="lock"/>}
onChangeText={text => onInputChange("password", text)}
style={styles.textInput}/>
</Card>
<View style={styles.buttonRow}>
<Button
color={disabled ? "gray" : undefined}
disabled={disabled}
mode={'contained'}
icon={'login'}
onPress={() => {
console.log("TAG isUserSignedIn: " + fbContext?.isuserSignedIn)
//fbContext?.testLog()
//console.log("TAG LOGIN BTN PRESSED")
//navigation.navigate('HomeScreen')
}}>Login</Button>
</View>
</View>
);
}
This is my App.js:
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import {StackScreens} from './src/helpers/types';
import { NavigationContainer, useNavigationContainerRef } from '#react-navigation/native';
import LoginScreen from './src/screens/LoginScreen/LoginScreen';
import HomeScreen from './src/screens/HomeScreen/HomeScreen';
import {doc, getFirestore, onSnapshot, setDoc, Unsubscribe as UnsubscribeFS} from 'firebase/firestore';
import { FirebaseContextProvider, FirebaseContext } from './src/context/FirebaseContext';
import { useContext } from 'react';
//import { navigationRef } from './RootNavigation';
//const userDocument = firestore().collection("users").doc('Cstl3bA9xwwH3UwHZJhA').get();
const Stack = createNativeStackNavigator();
export default function App() {
return (
<FirebaseContextProvider>
<Content />
</FirebaseContextProvider>
);
}
export const Content = () => {
const navigationRef = useNavigationContainerRef();
const firebaseContext = useContext({FirebaseContext});
return (
<NavigationContainer ref={navigationRef}>
<Stack.Navigator initialRouteName="LoginScreen">
<Stack.Screen name="LoginScreen" component={LoginScreen} />
<Stack.Screen name="HomeScreen" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Don't know what I have missed, I have installed the packages, I have tried to log different values but all seem to be undefined :/
I believe it is undefined because you're trying to destructure the context value, maybe
const { fbContext } = useContext(FirebaseContext);
should be
const fbContext = useContext(FirebaseContext);
For someone getting undefined from context, check on which level you placed your context provider. If you want to use context in a component you should wrap this component in a context provider outside of this component!
Incorrect way
const Component = () => {
const { value1, value2 } = useContext(MyContext); //here context value will be undefined
return (
<ContextProvider>
//Component content
</ContextProvider>
)
}
Correct way
const ComponentA = () => {
const { value1, value2 } = useContext(MyContext);
return(//Component A content)
}
const ComponentB = () => {
return(
<ContextProvider>
<ComponentA/>
</ContextProvider>
)
}

Error in render method of App.js? React-Native question

Pasted below is my code:
import React, {useState} from 'react';
import {View, StyleSheet, Flatlist, Alert} from 'react-native';
import 'react-native-get-random-values';
import {v4 as uuidv4} from 'uuid';
import {AddTask} from './src/screens/AddTask';
import {TaskList} from './src/screens/TaskList';
const App = () => {
const [tasks, setTasks] = useState([{id: uuidv4(), text: 'Task 1'}]);
const deleteTask = (id) => {
setTasks((prevTasks) => {
return prevTasks.filter((task) => task.id != id);
});
};
const addTask = (text) => {
if (!text) {
Alert.alert('Error', 'Please enter a task', {text: 'Ok'});
} else {
setTask((prevTask) => {
return [{id: uuid(), text}, ...prevTask];
});
}
};
return (
<View style={styles.container}>
<AddTask addTask={addTask} />
<Flatlist
data={tasks}
renderItem={({task}) => (
<TaskList item={task} deleteTask={deleteTask} />
)}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 10,
},
});
export default App;
I get an error about my render method:
ERROR Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
After Googling a bit people told me to check my imports, but I swear they are done correctly. Could someone help me understand this? I am building a task manager and I am looking to implement Redux later but I am simply seeking to build the app first: add redux later.
Full Github Project: https://github.com/calebdockal/TaskManagerApp2
There are few changes to be done in the code.
In the import statement remove curly brackets around AddTask and TaskList
import AddTask from './src/screens/AddTask';
import TaskList from './src/screens/TaskList';
Change Flatlist to FlatList in import statement
import {View, StyleSheet, FlatList, Alert} from 'react-native';
and change in return statement. Then update variable in renderItem from task to item and item to task as show below
<FlatList data={tasks}
renderItem={({item}) => (
<TaskList task={item} deleteTask={deleteTask} />
)}
/>
Full code below
import React, {useState} from 'react';
import {View, StyleSheet, FlatList, Alert, Text} from 'react-native';
import 'react-native-get-random-values';
import {v4 as uuidv4} from 'uuid';
import AddTask from './src/screens/AddTask';
import TaskList from './src/screens/TaskList';
const App = () => {
const [tasks, setTasks] = useState([{id: uuidv4(), text: 'Task 1'}]);
const deleteTask = (id) => {
setTasks((prevTasks) => {
return prevTasks.filter((task) => task.id != id);
});
};
const addTask = (text) => {
if (!text) {
Alert.alert('Error', 'Please enter a task', {text: 'Ok'});
} else {
setTasks((prevTask) => {
return [{id: uuidv4(), text}, ...prevTask];
});
}
};
return (
<View style={styles.container}>
<AddTask addTask={addTask} />
<FlatList
data={tasks}
renderItem={({item}) => (
<TaskList task={item} deleteTask={deleteTask} />
)}
/>
)}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 10,
},
});
export default App;
I have taken your code from github and updated the code. You can check here
https://snack.expo.io/FbOC0J!MM
You need to add import React from 'react' at top of your code

Display of API results with forEach in React Native

I'm trying to display data from an api and cant get a hold of using the forEach method correctly to show all the data at the same time. The API is working correctly. Here's the code:
import React, {useEffect, useState} from 'react'
import { Text, View, ActivityIndicator, ScrollView } from 'react-native'
import axios from '../../utils/axios'
//import CurrencyPair from '../../CurrencyPair'
function HomeScreen() {
const [data, setData] = useState([])
const [isLoading, setIsloading] = useState(true)
useEffect(() => {
const fetchpairs = async() => {
const result = await axios.get('/v3/accounts/{AccountId}/pricing?instruments=EUR_USD%2CUSD_CAD')
console.log(result.data)
setData(result.data)
setIsloading(false)
}
fetchpairs()
}, [])
if(isLoading) {
return (
<ActivityIndicator size="large"/>
)
}
else
return (
<ScrollView>
{[data].map((data) => (
data.forEach(data =>{
<Text>{JSON.stringify(data.prices[0].instrument)}
{JSON.stringify(data.prices[0].closeoutAsk)}
{JSON.stringify(data.prices[0].closeoutBid)}
</Text>
})
))}
</ScrollView>
)
}
export default HomeScreen
Map is already taking care of forEach function
<ScrollView>
{[data].map((item,i) => {
return(<Text key={i}>{JSON.stringify(item.prices[0].instrument)}
{JSON.stringify(item.prices[0].closeoutAsk)}
{JSON.stringify(item.prices[0].closeoutBid)}
</Text>
)}
)}
</ScrollView>

Categories