React Native App Wont display Api results - reactjs

Hello i'm trying to display the ai of these movies but the wont show on my phone but when i console log they work in my terminal, just having issues displaying the results to the device.
At first i wast giving a error
Uncaught TypeError:state.results.map is not an object
here is the code below
import React ,{ useState }from 'react';
import axios from'axios';
import { StyleSheet, Text, View ,ScrollView,TextInput} from 'react-native';
export default function App() {
const apiurl = "http://www.omdbapi.com/?i=tt3896198&apikey=?????";
const [state,setState] = useState({
s:'Enter A Movie...',
results:[],
selected:{}
});
const search = () => {
axios(apiurl + "&s=" + state.s).then(({data})=>{
let results = data.Search
console.log(results)
setState(prevState =>{
return {...prevState, results: results}
})
})
}
return (
<View style={styles.container}>
<Text style={styles.Header}>Movie DataBase</Text>
<TextInput
style={styles.searchBar}
onChangeText={text => setState(prevState =>{
return{...prevState, s: text}
})}
onSubmitEditing={search}
value = {state.s}
/>
<ScrollView style={styles.results}>
{state.results.map(result => {
<View key={result.imdbID} style={styles.result}>
<Text>{result.Title}</Text>
</View>
})}
</ScrollView>
</View>
);
}

You can directly set your results to your state like
setState( { ...state , results : results } )

Related

Firebase | Reading data from Firebase returns "undefined", but console.log shows precise result

EDIT: I'm new to Stack, but why was my earlier thread locked? It just said "similar thread is found somewhere else" and the thread wasn't at all similar.
I am currently trying to update my own little personal weight tracker using Firebase and React Native. However, whenever I log DataSnapshot.val() I receive the input 22, which is perfect. But when I return the very same value I receive Undefined.
I tried both get() and onValue() with the same results. The path is correct, since I get the correct data using console.log.
https://firebase.google.com/docs/database/web/read-and-write?authuser=2
I tried following the above documentation. But is it updated? snapshot is currently DataSnapshot?
Firebase:
const readWeight = (database, userId) => {
get(ref(database, `users/${userId}/weight`)).then((DataSnapshot) => {
try {
if (DataSnapshot.exists()) {
console.log(
`Weight found. Current weight is: ${DataSnapshot.val()} kg`
);
return DataSnapshot.val();
} else {
console.log("Weight wasn't found");
}
} catch (error) {
console.log(error);
}
});
};
HomeScreen.js
// Modules
import { react, useState, useEffect } from "react";
import { Text, TouchableOpacity, View, TextInput, Image } from "react-native";
import { LogOutButton } from "../Components/LogOutButton";
import { auth, writeUserData, database, readWeight } from "../firebase";
// Stylesheet
import { styles } from "../Stylesheet/Stylesheet";
export const HomeScreen = () => {
const user = auth.currentUser;
let currentUserWeight = readWeight(database, user.uid);
console.log("Current Weight: ", currentUserWeight);
return (
<View style={styles.profileMain}>
<View style={styles.profileInfoContainer}>
<View style={styles.HOME__profileWeightContainer}>
<Text style={styles.HOME__profileWeightText}>
Last Weight: {currentUserWeight}
</Text>
</View>
</View>
</View>
</View>
);
};
Data is loaded from Firebase asynchronously, and the return DataSnapshot.val() runs way after you actually call readWeight(database, user.uid). Adding some logging is probably the best way to see that flow.
The solution is to store the weight in the state of your component with the useState hook.
export const HomeScreen = () => {
const user = auth.currentUser;
// 👇
let { currentUserWeight, setCurrentUserWeight } = useState(0);
useEffect(() => {
const unsubscribe = get(ref(database, `users/${userId}/weight`)).then((DataSnapshot) => {
if (DataSnapshot.exists()) {
setCurrentUserWeight(DataSnapshot.val());
}
});
return () => unsubscribe();
, []}
// 👆
return (
<View style={styles.profileMain}>
<View style={styles.profileInfoContainer}>
<View style={styles.HOME__profileWeightContainer}>
<Text style={styles.HOME__profileWeightText}>
Last Weight: {currentUserWeight}
</Text>
</View>
</View>
</View>
</View>
);
};

Expo Refresh only working in certain components

so I am just digging into building apps with React Native/Expo and I have come across a weird behavior that I am not sure why is happening. I have a dashboard component that returns a 'UsersFlatList' component
const DashBoard = () => {
return (
<>
<View style={styles.dashboard__wrapper}>
<TextInput
placeholder="why is this working??
"
style={styles.form__input}
></TextInput>
<UsersFlatList />
</View>
</>
)
}
If I change that text - I see the changes happening in expo go immediately. However if I make changes to the data in the flatlist, I don't see any changes at all and I have to refresh the app to see any of the updates changes.
import { useEffect, useState } from "react"
import { Text, View, SafeAreaView, FlatList, StyleSheet } from "react-native"
import UserCard from "./UserCard"
import { collection, getDocs } from "firebase/firestore"
import db from "../firebaseConfig"
const UsersFlatList = () => {
const [onlineUsers, setOnlineUsers] = useState([])
useEffect(() => {
const fetchAllData = async () => {
const foundUsers = await getDocs(collection(db, "users"))
const currentUsers = []
foundUsers.forEach((user) => currentUsers.push(user.data()))
setOnlineUsers(() => currentUsers)
}
const matchedUsers = fetchAllData()
}, [])
return (
<FlatList
data={onlineUsers}
renderItem={UserCard}
keyExtractor={(item) => item.email}
></FlatList>
)
}
export default UsersFlatList
import { Text, View, StyleSheet } from "react-native"
const UserCard = ({ item }) => {
console.log(item)
return (
<View style={styles.userCard}>
<View style={styles.online__icon}></View>
<Text>{item.username} is a</Text>
</View>
)
}
const styles = StyleSheet.create({})
export default UserCard
Appreciate this is a long one to read but any help or a pointer would be amazing thanks

I can't make run the blemanager.start because promise rejection id:0 null is not an object

I can't start the ble manager in my code.
I use expo.
I tried a lot of solutions I found on internet but none worked for me.
When i get out the blemanager.start my app run correctly.
I don't find any kind of doc about promise in React native... There is my code. I really hope you can help me.
import { Stylesheet, View, Text, Button, TouchableOpacity,FlatList, Alert,NativeAppEventEmitter } from 'react-native'
import donnee from '../Donnee/data'
import DataItem from './DataItem'
import FilmDetail from './FilmDetail';
import BleManager from 'react-native-ble-manager';
import React, { useState, useEffect } from 'react';
//import BleManager from 'react-native-ble-plx';
const width_proportion = '60%';
const Lwidth_proportion = '30%';
const maxwidth="100%";
const heightinside="12%";
const paddleft = '10%';
class Search extends React.Component {
componentDidMount() {
console.log('bluetooth scanner mounted');
NativeAppEventEmitter.addListener('BleManagerDiscoverPeripheral',(data) =>
{
let device = 'device found: ' + data.name + '(' + data.id + ')';
if(this.devices.indexOf(device) == -1) {
this.devices.push(device);
}
let newState = this.state;
newState.dataSource = newState.dataSource.cloneWithRows(this.devices);
this.setState(newState);
});
BleManager.start({ showAlert: false }).then(() => {
// Success code
console.log("Module initialized");
});
}
startScanning() {
console.log('start scanning');
}
render() {
return (
<View>
<View style={styles.entete}></View>
<View>
<TouchableOpacity style = {styles.filtrebtn} onPress={() => this.props.navigation.navigate("FilmDetail")}>
<Text style = {styles.textfiltre}>FILTRES</Text>
</TouchableOpacity>
<TouchableOpacity style = {styles.scan} onPress={() => this.startScanning()}>
<Text style = {styles.textscan}>SCAN</Text>
</TouchableOpacity>
</View>
<View>
<FlatList
data={donnee}
keyExtractor={(item) => item.id.toString()}
renderItem={({item}) =><DataItem donnees={item}/> } />
</View>
</View>
)
}
}
export default Search
expo can not work with the ble-manager. You need to use the native package by running the
npx react-native init AwesomeProject
and you need mac not a window

Accessing Refs in React Functional Component

Im using this package to add credit cards to my app, how would you åccess the refs as in the example when using this in a functional component?
This is how they show to update values:
this.refs.CCInput.setValues({ number: "4242" });
I don't know how to access that inside a functional component?
This is my component to Edit a card, and I want to add the current values to the inputs.
import React, {useContext, useState, useRef} from 'react';
import {Text, View, StyleSheet, TouchableOpacity} from 'react-native';
import {CreditCardInput} from 'react-native-input-credit-card';
import Store from '../../store/context';
const styles = StyleSheet.create({
});
export default function EditCard(props) {
const {navigate} = props.navigation;
const {cardNumber} = props.navigation.state.params;
const {state, dispatch} = useContext(Store);
const [card, setCard] = useState(
state.cards.find(card => {
return card.values.number === cardNumber;
}),
);
const _onChange = form => {
if (form.valid) {
setCard(form);
}
};
const updateCard = () => {
dispatch({
type: 'ADD_CARD',
payload: card,
});
navigate.goBack();
};
return (
<View style={styles.container}>
<CreditCardInput
validColor={'#47B278'}
invalidColor={'#E23C3C'}
placeholderColor={'#efefef'}
onChange={_onChange}
requiresName
/>
<TouchableOpacity
style={
card
? card.valid
? styles.button
: styles.buttonDisabled
: styles.buttonDisabled
}
disabled={card ? (card.valid ? false : true) : true}
onPress={updateCard}>
<Text style={styles.buttonText}>Update Credit Card</Text>
</TouchableOpacity>
</View>
);
}
You need to use useRef hook:
const cciRef = useRef();
<CreditCardInput ref={cciRef}/>;
// cciRef.current holds the reference
export default function EditCard(props) {
const cciRef = useRef();
useEffect(() => {
console.log(cciRef.current);
cciRef.current.setValues({ number: "4242" });
}, []);
return (
<View style={styles.container}>
<CreditCardInput ref={cciRef} />
</View>
);
}

Button not displaying fetch results to the component?

I am creating a currency converter app and it will retrieve currency value from the API and multiply with the text input for the result. Both the API result and Text input are stored in State and passing as props to the Component
import React from 'react';
import { StyleSheet, Text, View,TextInput,Button } from 'react-native';
import DisplayResult from './src/DisplayResult'
export default class App extends React.Component {
state = {
currency:'',
pokeList: '',
}
placeNameChangeHandler=(val)=>{
this.setState({currency:val});
}
// console.log(this.state.currency);
async findCurrency () {
try {
//Assign the promise unresolved first then get the data using the json method.
const pokemonApiCall = await fetch('https://free.currconv.com/api/v7/convert?q=KWD_INR&compact=ultra&apiKey={my_api_Key}');
const pokemon = await pokemonApiCall.json();
this.setState({pokeList: pokemon['KWD_INR']});
// console.log(pokemon);
} catch(err) {
console.log("Error fetching data-----------", err);
};
<DisplayResult convert={this.state.pokeList} result={this.state.currency} />
}
render() {
return (
<View style={styles.container}>
<TextInput
placeholder="Currency"
value = {this.state.currency}
onChangeText={this.placeNameChangeHandler}
/>
<Button
title="Search"
onPress={this.findCurrency.bind(this)}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
DisplayResult
const DisplayResult =(props)=>{
const {convert,result} = props
console.log(convert);
return (
<View>
<Text>{result*convert}</Text>
</View>
)
}
export default DisplayResult;
I am trying to pass the API result and text input to the display component and this will multiply the values and will give the result.
Now this is not functioning or giving result
why this is not showing and where it's going wrong?
In your findCurrency method you just "call" the DisplayResult without returning it, but I don't think this is the good method to display your result.
You can use your component directly within the render method by testing your state variables, like this :
findCurrency = async () => {
try {
const pokemonApiCall = await fetch(
"https://free.currconv.com/api/v7/convert?q=KWD_INR&compact=ultra&apiKey={my_api_Key}"
);
const pokemon = await pokemonApiCall.json();
this.setState({ pokeList: pokemon["KWD_INR"] }); // You set your "pokeList" variable up
} catch (err) {
console.log("Error fetching data-----------", err);
}
}
Note that you remove the DisplayResult call here and the function became an arrowed function, then in your render method use the test to make your result appear only if pokeList isn't empty :
render() {
return (
<View style={styles.container}>
<TextInput
placeholder="Currency"
value={this.state.currency}
onChangeText={this.placeNameChangeHandler}
/>
<Button title="Search" onPress={this.findCurrency.bind(this)} />
{this.state.pokeList !== "" && (
<DisplayResult
convert={this.state.pokeList}
result={this.state.currency}
/>
)}
</View>
);
}
Then, you don't have to bind your function in the onPress method like this, JavaScript immediately calls the function if you do this, instead, use arrow functions, you can access this by doing so in your function AND the onPress method doesn't call it if you don't click on the button, you just have to specify which function to execute when clicked :
<Button title="Search" onPress={this.findCurrency} />
If you have parameters in your function, use an arrow function instead :
<Button title="Search" onPress={() => yourFunction(param)} />
This should do the trick.
Try writing your function like that :
const findCurrency = async() => {
// ...
};
and call it like that
<Button
title="Search"
onPress={() => this.findCurrency()}
/>
I personnaly never use .bind because I think this is very unclear.
try using conditional rendering,
if data fetched, then only render.
import React from 'react';
import { StyleSheet, Text, View,TextInput,Button } from 'react-native';
import DisplayResult from './src/DisplayResult'
export default class App extends React.Component {
state = {
currency: '',
pokeList: '',
}
placeNameChangeHandler=(val)=>{
this.setState({currency:val});
}
// console.log(this.state.currency);
this.findCurrency.bind(this);
async findCurrency () {
try {
//Assign the promise unresolved first then get the data using the json method.
const pokemonApiCall = await fetch('https://free.currconv.com/api/v7/convert?q=KWD_INR&compact=ultra&apiKey={my_api_Key}');
const pokemon = await pokemonApiCall.json();
this.setState({pokeList: pokemon['KWD_INR']});
// console.log(pokemon);
} catch(err) {
console.log("Error fetching data-----------", err);
};
}
render() {
return (
<View style={styles.container}>
<TextInput
placeholder="Currency"
value = {this.state.currency}
onChangeText={this.placeNameChangeHandler}
/>
<Button
title="Search"
onPress={this.findCurrency()}
/>
</View>
{
if(this.state.pokeList !== '' || this.state.currency !== '') ?
<DisplayResult convert={this.state.pokeList} result={this.state.currency} /> : <div></div>
}
);
}
}

Resources