Undefined result after passing to the next screen using random function - react-native

I am having trouble on a undefined value I get after passing from one screen (Home) to another screen (SubScreen2) after randomizing the value in a drop down picker
Home
import { TouchableOpacity, StyleSheet, Text, View } from 'react-native'
import React from 'react'
import { auth } from '../firebase'
import { useNavigation } from '#react-navigation/core'
import { signOut } from 'firebase/auth'
import DropDownPicker from 'react-native-dropdown-picker'
import { useEffect, useState } from 'react'
const HomeScreen = () => {
const navigation = useNavigation()
const [open, setOpen] = useState(false);
const [value, setValue] = useState(null);
const [items, setItems] = useState([
{label: 'Fast Food', value: 'Fast Food'},
{label: 'Western', value: 'Western'},
{label:'Beverage', value:'Berverage'},
{label:'Chinese', value:'Chinese'},
{label: 'Korean', value: 'Korean'},
{label: 'Taiwanese', value: 'Taiwanese'},
{label: 'Malay', value: 'Malay'},
{label: 'Indonesian', value: 'Indonesian'},
{label: 'Indian', value: 'Indian'},
{label: 'Vietnamese', value: 'Vietnamese'},
{label: 'Japanese', value: 'Japanese'},
{label: 'Italian', value: 'Italian'},
{label: 'Desserts', value: 'Desserts'},
{label: 'Others', value: 'Others'},
]);
const handleSignOut = async () =>{
try{
await signOut(auth)
console.log("Signed out successfully")
navigation.replace("Login")
}catch (error) {
console.log({error});
}
}
const setRandomValue = () => {
const randomIndex = Math.floor(Math.random() * items.length);
const randomValue = setValue([items[randomIndex].label.toLowerCase()]);
console.log(randomIndex)
console.log(randomValue)
navigation.navigate("SubScreen2", {paramKey:randomValue})
}
return (
<View style = {styles.container}>
<Text>Welcome {auth.currentUser?.email}</Text>
<Text></Text>
<Text>What cusine would you like to eat today?</Text>
<DropDownPicker
open={open}
value={value}
items={items}
setOpen={setOpen}
setValue={setValue}
setItems={setItems}
/>
<TouchableOpacity
onPress={() => navigation.navigate("SubScreen1", {paramKey:value})}
style = {styles.button}
>
<Text style = {styles.buttonText}>Search</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={setRandomValue}
style = {styles.button}
>
<Text style = {styles.buttonText}>Random</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={handleSignOut}
style = {styles.button}
>
<Text style = {styles.buttonText}>Sign Out</Text>
</TouchableOpacity>
</View>
)
}
export default HomeScreen
SubScreen2
import { StyleSheet, Text, View } from 'react-native'
import React from 'react'
const SubScreen2 = ({route}) => {
const paramKey = route.params.paramKey
console.log(paramKey)
return (
<View>
<Text>{paramKey}</Text>
</View>
)
}
export default SubScreen2
const styles = StyleSheet.create({})
Under the function of setRandomValue in my Home, I have 2 variables which are randomIndex and randomValue. I can get a numeric output from randomIndex but a undefined output from randomValue. From here I pass the value to the next page (SubScreen2) via paramKey. The output I get is undefined here as in the previous page the output was undefined. So here is the question, what am I doing something wrong here? I am trying to randomize the value and move it to the next page so then I can continue using the value and search thru firebase database to extract the data I need. Example, Lets say the computer decides to pick Japanese, this Japanese will be passed to the 2nd page (SubScreen2) and within SubScreen2, Japanese will be used to search thru the firebase database to extract Japanese related and display on the page.

The problem is that you're assigning the setValue setState function to the randomValue instead of the actual value.
const setRandomValue = () => {
const randomIndex = Math.floor(Math.random() * items.length);
const randomValue = items[randomIndex].label.toLowerCase(); // only assigning the label
setValue(randomValue);
console.log(randomIndex);
console.log(randomValue);
navigation.navigate("SubScreen2", { paramKey: randomValue });
};

Related

MobX observable changes not updating components

I have a store in MobX that handles containing the cart, and adding items to it. However, when that data is updated the components don't re-render to suit the changes.
I tried using useEffect to set the total price, however when the cartData changes, the state is not updated. It does work on mount, though.
In another component, I call addItemToCart, and the console.warn function returns the proper data - but that data doesn't seem to be synced to the component. clearCart also seems to not work.
My stores are contained in one RootStore.
import React, {useState, useEffect} from 'react';
import {List, Text} from '#ui-kitten/components';
import {CartItem} from '_molecules/CartItem';
import {inject, observer} from 'mobx-react';
const CartList = (props) => {
const {cartData} = props.store.cartStore;
const [totalPrice, setTotalPrice] = useState(0);
const renderCartItem = ({item, index}) => (
<CartItem itemData={item} key={index} />
);
useEffect(() => {
setTotalPrice(cartData.reduce((a, v) => a + v.price * v.quantity, 0));
console.warn('cart changed!');
}, [cartData]);
return (
<>
<List
data={cartData}
renderItem={renderCartItem}
style={{backgroundColor: null, width: '100%'}}
/>
<Text style={{textAlign: 'right'}} category={'s1'}>
{`Total $${totalPrice}`}
</Text>
</>
);
};
export default inject('store')(observer(CartList));
import {decorate, observable, action} from 'mobx';
class CartStore {
cartData = [];
addItemToCart = (itemData) => {
this.cartData.push({
title: itemData.title,
price: itemData.price,
quantity: 1,
id: itemData.id,
});
console.warn(this.cartData);
};
clearCart = () => {
this.cartData = [];
};
}
decorate(CartStore, {
cartData: observable,
addItemToCart: action,
clearCart: action,
});
export default new CartStore();
I have solved the issue by replacing my addItemToCart action in my CartStore with this:
addItemToCart = (itemData) => {
this.cartData = [
...this.cartData,
{
title: itemData.title,
price: itemData.price,
quantity: 1,
id: itemData.id,
},
];
console.warn(this.cartData);
};

How to setting state with navigation params?

I am working on a React-native project with its basic packets(navigation etc). I have two screens. First there is a button and when i click the button. It's navigate to another screen which has flatlist. Then i click value in flatlist it is gives me a value . I can send that value to first screen with this.props.navigation.navigate and i can show it in console but i dont know how to use it to change buttonText which in my first screen? Where should i use setstate function in first screen ? (sorry for english)
Home.js
import React, {Component} from 'react';
import {View, Text} from 'react-native';
import {InputWithButton} from '../components/TextInput';
//const TEMP_BASE_CURRENCY = 'USD';
//const TEMP_CONVERT_CURRENCY = 'GBP';
class Home extends Component {
constructor(props) {
super(props);
this.state = {
baseCurrency: 'TRY', //Başlangıç olarak sayfa açıldığında gelecek olan değerler
convertCurrency: 'USD',
amount: null,
result: '',
date: '',
};
//const selected = this.props.route.params;
}
calculate = () => {
const amount = this.state.amount;
let url =
'https://api.exchangeratesapi.io/latest?base=' + this.state.baseCurrency;
fetch(url, {
method: 'GET',
})
.then((res) => res.json())
.then((data) => {
const date = data.date;
const result = (
data.rates[this.state.convertCurrency] * amount
).toFixed(2);
this.setState({
result,
date,
});
})
.catch((error) => {
console.log(error);
});
};
handleChangeText = (text) => {
//Yazıda değişim algılandığında api işlemleri başlasın
this.setState(
{
amount: text,
},
this.calculate,
);
};
handlePressBaseCurrency = () => {
//flatlist sayfası açılsın
const {navigation} = this.props;
navigation.navigate('CurrencyList');
};
handlePressConvertCurrency = () => {
//flatlist sayfası açılsın
};
render() {
const {baseCurrency, convertCurrency, amount, result, date} = this.state;
return (
<View>
<InputWithButton
buttonText={baseCurrency}
onPress={this.handlePressBaseCurrency}
keyboardType="numeric"
onChangeText={(text) => this.handleChangeText(text)}
/>
<InputWithButton
editable={false}
buttonText={convertCurrency}
onPress={this.handlePressConvertCurrency}
value={result}
/>
</View>
);
}
}
export default Home;
CurrencyList.js
import React, {Component} from 'react';
import {View, FlatList, Text} from 'react-native';
import currencies from '../data/currencies';
import {ListItem, Separator} from '../components/List';
const temp_base_currency = 'CAD';
class CurrencyList extends Component {
constructor(props) {
super(props);
this.state = {
selectedItem: '',
};
}
handlePress = (item) => {
this.setState({
selectedItem: item, //__
});
// const {navigate} = this.props.navigation;
// navigate('Home', {clickedItem: this.state.selectedItem});
//Tıklandığında beklesin
setTimeout(
() => this.props.navigation.navigate('Home', {selected: item}),
1,
); //__
};
render() {
return (
<View>
<FlatList
renderItem={({item}) => (
<ListItem
onPress={() => this.handlePress(item)}
text={item}
selected={item === this.state.selectedItem} //__
/>
)}
data={currencies}
keyExtractor={(item) => item}
ItemSeparatorComponent={Separator}
/>
</View>
);
}
}
export default CurrencyList;
It would have been better if you shared your code but here is what I would do.
SECOND SCREEN
this.props.navigation.navigate('firstScreen', {
name: 'Your value'
})
FIRST SCREEN
const name = this.props.route.params.name;
<Button>{name}</Button
You can pass the selected item from the Flatlist to the Home screen like this:
Home.js:
this.props.navigation.navigate('CurrencyList',
{
onGoback: (item) => this.setState({})
})
CurrencyList.js:
handlePress: (item) => {
/** your code **/
this.props.navigation.state.params.onGoBack(item)
this.props.navigation.navigate('Home')
}

React Native State is Undefined Vasern

I am actually starting with Mobile Development and React Native and I thought an interesting Database called Vasern But now I am trying to load things from my database with the componentDidMount() method but i actually just get this Error everytime.
I am sure its just a trivial Error but i just cant find it...
Thanks in Advance
import React, {Component} from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
Button,
SectionList
} from 'react-native';
import Vasern from 'vasern';
import styles from './styles';
const TestSchema = {
name: "Tests",
props: {
name: "string"
}
}
const VasernDB = new Vasern({
schemas: [TestSchema],
version: 1
})
const { Tests } = VasernDB;
var testList = Tests.data();
class Main extends Component {
state = {
tests: [],
};
constructor(props){
super(props);
this._onPressButton = this._onPressButton.bind(this);
this._onPressPush = this._onPressPush.bind(this);
this._onPressUpdate = this._onPressUpdate.bind(this);
this._onPressDeleteAll = this._onPressDeleteAll.bind(this);
}
componentDidMount() {
Tests.onLoaded(() => this._onPressButton());
Tests.onChange(() => this._onPressButton());
}
_onPressButton = () => {
let tests = Tests.data();
console.log(tests);
//if( tests !== undefined){
this.setState({tests}); // here is the error
//alert(tests);
//}
}
_onPressPush = () => {
Tests.insert({
name: "test"
});
console.log(this.state.tests + "state tests"); //here the console only shows the text
}
_onPressUpdate = () => {
var item1 = Tests.get();
Tests.update(item1.id, {name: "test2"});
}
_onPressDelete = () => {
}
_onPressDeleteAll = () => {
let tests = Tests.data();
tests.forEach((item, i) => {
Tests.remove(item.id)
});
}
_renderHeaderItem({ section }) {
return this._renderItem({ item: section});
}
_renderItem({ item }){
return <View><Text>{item.name}</Text></View>
}
render() {
//const { tests = [] } = this.props;
return (
<View style={styles.container}>
<View>
<TextInput> Placeholder </TextInput>
<Button title="Press me for Show" onPress={this._onPressButton}/>
<Button title="Press me for Push" onPress={this._onPressPush}/>
<Button title="Press me for Update" onPress={this._onPressUpdate}/>
<Button title="Press me for Delete" onPress={this._onPressDelete}/>
<Button title="Press me for Delete All" onPress={this._onPressDeleteAll}/>
</View>
<View style={styles.Input}>
<SectionList
style={styles.list}
sections={this.state.tests}
keyExtractor={item => item.id}
renderSectionHeader={this._renderHeaderItem}
contentInset={{ bottom: 30 }}
ListEmptyComponent={<Text style={styles.note}>List Empty</Text>}
/>
</View>
</View>
);
}
}
export default Main;
Since Tests.data() will return an array (as list of records).
In React Native, you might use FlatList to display an array of records.
import { ..., FlatList } from 'react-native';
...
// replace with SectionList
<FlatList
renderItem={this._renderItem} // item view
data={this.state.tests} // data array
style={styles.list}
keyExtractor={item => item.id}
contentInset={{ bottom: 30 }}
ListEmptyComponent={<Text style={styles.note}>List Empty</Text>}
/>
In case you want to use SectionList, you will need to reform data into sections. Something like:
var sections = [
{title: 'Title1', data: ['item1', 'item2']},
{title: 'Title2', data: ['item3', 'item4']},
{title: 'Title3', data: ['item5', 'item6']},
]
Besides, React Native is in a really good state. I think you will like it.

How do I take a screenshot of View in React Native?

I want to share screenshot of particular View Component instead of whole screen.
Any one help me out with this.
Take a look a picture. Want screenshot of Red mark area which is within View Component.
You can use library named react-native-view-shot
You just have to give wrap your View inside ViewShot, take a reference of that and call capture()
Here is example of code taken from that library
import ViewShot from "react-native-view-shot";
class ExampleCaptureOnMountManually extends Component {
componentDidMount () {
this.refs.viewShot.capture().then(uri => {
console.log("do something with ", uri);
});
}
render() {
return (
<ViewShot ref="viewShot" options={{ format: "jpg", quality: 0.9 }}>
<Text>...Something to rasterize...</Text>
</ViewShot>
);
}
}
Here is a working example example of code using react-native-view-shot with hooks
import React, { useState, useRef, useEffect } from "react";
import { View, Image, ScrollView, TouchableOpacity } from "react-native";
import ViewShot from "react-native-view-shot";
var RNFS = require("react-native-fs");
import Share from "react-native-share";
const TransactionReceipt = () => {
const viewShotRef = useRef(null);
const [isSharingView, setSharingView] = useState(false);
useEffect(() => {
if (isSharingView) {
const shareScreenshot = async () => {
try {
const uri = await viewShotRef.current.capture();
const res = await RNFS.readFile(uri, "base64");
const urlString = `data:image/jpeg;base64,${res}`;
const info = '...';
const filename = '...';
const options = {
title: info,
message: info,
url: urlString,
type: "image/jpeg",
filename: filename,
subject: info,
};
await Share.open(options);
setSharingView(false);
} catch (error) {
setSharingView(false);
console.log("shareScreenshot error:", error);
}
};
shareScreenshot();
}
}, [isSharingView]);
return (
<ViewShot ref={viewShotRef} options={{ format: "jpg", quality: 0.9 }}>
<View>
{!isSharingView && (
<TouchableOpacity onPress={() => setSharingView(true)}>
<Image source={Images.shareIcon} />
</TouchableOpacity>
)}
<ScrollView />
</View>
</ViewShot>);
}

Error Rendering an Array of Custom Components in React Native

I am trying to render an array of (custom-built) React Native components, but I am getting the following error when I try to do so:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of 'CategoryList'.
I have a component called CategoryList (which is a stateless component), and it renders a collection of Category components. They are defined below:
CategoryList:
import React, { PropTypes } from 'react';
import View from 'react-native';
import humps from 'humps';
import Category from './Category';
const CategoryList = ({ categories }) => {
const camelizedCategories = humps.camelizeKeys(categories);
const categoryElements = camelizedCategories.map(
(category, idx) => <Category {...category} key={idx} />
);
return (
<View>
{categoryElements}
</View>
);
};
CategoryList.propTypes = {
categories: PropTypes.arrayOf(
PropTypes.shape({
display_name: PropTypes.string.isRequired,
list_name: PropTypes.string.isRequired,
list_name_encoded: PropTypes.string.isRequired,
newest_published_date: PropTypes.string.isRequired,
oldest_published_date: PropTypes.string.isRequired,
updated: PropTypes.string.isRequired,
})
),
};
export default CategoryList;
Category:
import React from 'react';
import { View, Text } from 'react-native';
const Category = ({
displayName,
listName,
listNameEncoded,
newestPublishedDate,
oldestPublishedDate,
updated,
}) => {
return (
<View>
<Text>
{displayName}
</Text>
<Text>
{listName}
{listNameEncoded}
</Text>
<Text>
{listNameEncoded}
</Text>
<Text>
{newestPublishedDate}
</Text>
<Text>
{oldestPublishedDate}
</Text>
<Text>
{updated}
</Text>
</View>
);
};
Category.propTypes = {
displayName: React.PropTypes.string.isRequired,
listName: React.PropTypes.string.isRequired,
listNameEncoded: React.PropTypes.string.isRequired,
newestPublishedDate: React.PropTypes.string.isRequired,
oldestPublishedDate: React.PropTypes.string.isRequired,
updated: React.PropTypes.string.isRequired,
};
export default Category;
Finally, categories is being called as follows:
<CategoryList categories={mockedData} />
Where mockedData is being defined as follows:
const mockedData = [
{
list_name: 'Combined Print and E-Book Fiction',
display_name: 'Combined Print & E-Book Fiction',
list_name_encoded: 'combined-print-and-e-book-fiction',
oldest_published_date: '2011-02-13',
newest_published_date: '2016-08-21',
updated: 'WEEKLY',
},
{
list_name: 'Combined Print and E-Book Nonfiction',
display_name: 'Combined Print & E-Book Nonfiction',
list_name_encoded: 'combined-print-and-e-book-nonfiction',
oldest_published_date: '2011-02-13',
newest_published_date: '2016-08-21',
updated: 'WEEKLY',
},
];
Please check if import View from 'react-native' in CategoryList is a typo in question.
Should be import {View} from 'react-native'
If categories is empty, categoryElements is an empty array.
const categoryElements = camelizedCategories.map(
(category, idx) => <Category {...category} key={idx} />
);
Instead, the code should be:
const categoryElements = camelizedCategories.length > 0 ? camelizedCategories.map(
(category, idx) => <Category {...category} key={idx} />
) : null;