How to use react-native-action-sheet with hooks - javascript

I'm trying to use https://github.com/expo/react-native-action-sheet in a functional component using the provided hook useActionSheet(). I'm already using the class components version without any problem but I'd like to switch to functional.
React version is 16.9.0
This is my component
import {
connectActionSheet,
useActionSheet,
} from "#expo/react-native-action-sheet";
import React, { Component } from "react";
import { View, Text, SafeAreaView } from "react-native";
import TaButton from "../components/TaButton";
import { typography, styles, buttons } from "../components/Styles";
const UploadUI: React.FC<{
description: string;
label: string;
}> = (props) => {
const { showActionSheetWithOptions } = useActionSheet();
const openActionSheet = () => {
console.log("TEST - Choosing action now");
const options = [
"Scegli dalla libreria",
"Scatta una foto",
"Carica un file",
"Annulla",
];
//const destructiveButtonIndex = 0;
const cancelButtonIndex = options.length - 1;
showActionSheetWithOptions(
{
options,
cancelButtonIndex,
//destructiveButtonIndex,
},
(buttonIndex) => {
// Do something here depending on the button index selected
switch (buttonIndex) {
case 0:
console.log('Case 0')
return;
case 1:
console.log("Case 1");
return;
case 2:
console.log("Case 2");
return;
default:
}
}
);
};
const { description, label } = props;
return (
<View style={{ flexDirection: "row", height: 50, marginBottom: 30 }}>
<View style={{ flex: 0.7, justifyContent: "center" }}>
<Text style={typography.body}>{description}</Text>
</View>
<View style={{ flex: 0.3 }}>
<TaButton
style={buttons.primary}
labelStyle={buttons.primaryLabel}
onPress={() => openActionSheet()}
label={label}
/>
</View>
</View>
);
};
const URWStep4: React.FC = (props) => {
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
<View style={{ paddingVertical: 30, marginBottom: 20 }}>
<Text style={typography.title}>
Ci serviranno alcuni documenti per verificare la tua identità
</Text>
</View>
<UploadUI
description="Carta d'identità - Fronte"
label="Carica"
></UploadUI>
<UploadUI
description="Carta d'identità - Retro"
label="Carica"
></UploadUI>
</View>
</SafeAreaView>
);
};
export default connectActionSheet(URWStep4);
When clicking on buttons, the sentence "TEST - Choosing action now" is logged ad expected, but nothing more happens. The actionsheet does not open.

Check you have wrapped your top-level component with <ActionSheetProvider /> even when using hooks
https://github.com/expo/react-native-action-sheet#1-wrap-your-top-level-component-with-actionsheetprovider-

using useRef, I saw the issue in lib and Allanmaral's answer:
import ActionSheet from 'react-native-actionsheet'
const Demo = (props) => {
const refActionSheet = useRef(null);
showActionSheet = () => {
if (refActionSheet.current) {
refActionSheet.current.show();
}
}
return (
<View>
<Text onPress={this.showActionSheet}>Open ActionSheet</Text>
<ActionSheet
ref={refActionSheet}
title={'Which one do you like ?'}
options={['Apple', 'Banana', 'cancel']}
cancelButtonIndex={2}
destructiveButtonIndex={1}
onPress={(index) => { /* do something */ }}
/>
</View>
)
}

Related

Passing in variables on mapped components? (React Native)

I have this code:
import React, { useState } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
export default function App() {
let str = "Hello ^world text '^Some^' '^Random^' '^Example^' '^Text^' '^Some^' '^more^' '^random^' '^example^' '^text^'!"
let arr = str.split(/\s/g)
let wordBits
const [highlightedWords, setHighlightedWords] = useState(["world", "example", "random"])
function highlighter(word) {
setHighlightedWords((prevState) => {
return(
[word, ...prevState]
)
})
}
return (
<View style={styles.container}>
<Text>
{arr.map((el) => {
wordBits = el.split("^")
token = wordBits[1]
return (
<Text>
{wordBits[0]}
<View style={
highlightedWords.includes(wordBits[1]) ?
styles.highlighted :
styles.regular
}>
<Text onPress={() => {highlighter(wordBits[1])}}>
{wordBits[1]}
</Text>
</View>
{wordBits[2]}{" "}
</Text>
)
})}
</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
highlighted: {
backgroundColor: "yellow"
},
regular: {
color: "black"
}
});
I extract the word from surrounding characters and try to pass it in as a function on each component. But instead, it gets set to the final word that got mapped.
Is there a way to pass the words themselves, and not change as the variable changes?

React native onPress or any event is not working after sometime of app load

I am using react native thunder push where continually value fluctuation happening and i am showing data on screen using mobx state management tool. all things is working fine but when i am leave the screen for 2 minute then that events are not working screen is not freezing only events is not working.
STORE
import {observable,action,makeAutoObservable} from 'mobx';
class CommonMob {
data =[];
checkAppstate ='active';
deployeStatus = true;
queryString = '?creator_id=null&tags=&exchange=null&broker_id=null&instrument_type=null&execution=null&status=null&pnl=null&broker_id=';
userToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9hcGktYXBwLnRyYWRldHJvbi50ZWNoXC9hdXRoXC9zaWduLWluIiwiaWF0IjoxNjU0ODYzMjcyLCJleHAiOjIzNTQ3MDMyNzIsIm5iZiI6MTY1NDg2MzI3MiwianRpIjoicVF6TTJHUkdQS3kyY0NCeCIsInN1YiI6MjY3NTE5LCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3In0.QLDx1SUEJBheQbm-UqD8AOad5Oj3x3UWHBeShmn-2PE';
constructor() {
makeAutoObservable(this)
}
setData(res) {
this.data =res;
}
setAppState(val){
this.checkAppstate = val;
}
setdeployeStatus(val){
this.deployeStatus = val;
}
}
export default new CommonMob()
Screen
import {TouchableOpacity,View, Text, Button, FlatList, AppState,ScrollView,InteractionManager} from 'react-native';
import React, {useCallback, useEffect} from 'react';
import deployedStore from '../mob/deployedStore';
import {useIsFocused, useFocusEffect} from '#react-navigation/native';
import MarketStore from '../mob/deployedStore';
import {observer} from 'mobx-react-lite';
import {initThunderPush} from '../Service/ThunderConnection';
import {
fetchStrategies,
fetchFullStrategies,
} from '../Service/DeployeConnection';
import CommonStore from '../mob/commonStore';
import commonStore from '../mob/commonStore';
import Nav from '../Nav/Nav';
import { useNavigation } from '#react-navigation/native';
// import commonStore from '../mob/commonStore';
let listening = false;
const Deplyee = React.memo(observer(({navigation}) => {
// const navigation = useNavigation();
const navFun = ()=>{
alert("function call");
navigation.navigate("Dashboard")
}
useFocusEffect(
useCallback(() => {
// Do something when the screen is focused.
deployedStore.setisDeploye(true);
deployedStore.setisMarcketWatch(true);
commonStore.setdeployeStatus(true);
return () => {
// Do something when the screen is unfocused
deployedStore.setisDeploye(false);
deployedStore.setisMarcketWatch(false);
commonStore.setdeployeStatus(false);
};
}, []),
);
// React.useEffect(() => {
// }, [deployedStore.dataaa, deployedStore.strategies]);
React.useEffect(
() => {
InteractionManager.runAfterInteractions(() => {
// let timer = setTimeout(() => , 1000)
fetchFullStrategies(CommonStore.userToken);
fetchStrategies();
// fetchFullStrategies(CommonStore.userToken);
initThunderPush();
return () => {
clearTimeout(timer)
}
});
},
[[deployedStore.dataaa, deployedStore.strategies]]
)
React.useEffect(() => {
fetchStrategies();
}, [deployedStore.strategies]);
useFocusEffect(
React.useCallback(() => {
// fetchFullStrategies(CommonStore.userToken);
}, [deployedStore.strategies]),
);
React.useEffect(
() => {
if (!listening) {
initThunderPush();
listening = true;
}
setInterval(() => {
deployedStore.setCanState(true);
}, 1000);
},
[
/*strategies*/
],
);
useEffect(() => {
const appStateListener = AppState.addEventListener(
'change',
nextAppState => {
commonStore.setAppState(nextAppState);
},
);
return () => {
appStateListener?.remove();
};
}, []);
return (
<View>
<ScrollView>
<View
style={{
display: 'flex',
flexDirection: 'row',
width: '100%',
margin: 'auto',
flexWrap: 'wrap',
}}>
<Nav />
<TouchableOpacity onPress={() => alert("test pass")} ><Text>Test alert</Text></TouchableOpacity>
<TouchableOpacity onPress={() => navFun()} >
<Text>test function </Text>
</TouchableOpacity>
</View>
<Text>Deployed Strategies</Text>
{deployedStore.strategies.map(item => (
<View key={item.identifier}>
<Text style={{color: 'red', alignSelf: 'center'}}>
NAME - {item.template.name}
</Text>
<Text style={{color: 'blue', alignSelf: 'center'}}>
TYPE - {item.deployment_type}
</Text>
<Text style={{color: 'green', alignSelf: 'center'}}>
STATUS {item.status}
</Text>
<Text style={{color: 'orange', alignSelf: 'center', fontSize: 20}}>
{/* <Text style={item.sum_of_pnl >= 0 ? {color:green} : {color:red}}> */}
{item.country === 'IN'
? `${(item.sum_of_pnl, 0)} (${(
(item.sum_of_pnl /
(item.template.capital_required * item.minimum_multiple)) *
100
).toFixed(2)} %)`
: null}
</Text>
{/* <Text style={{color:'green', alignSelf:'center'}}>{item.ltp}</Text> */}
</View>
))}
<Text>market watch section</Text>
{deployedStore.dataaa.map(item => (
<View key={item.identifier}>
<Text style={{color: 'red', alignSelf: 'center'}}>
{item.identifier}
</Text>
<Text style={{color: 'green', alignSelf: 'center'}}>{item.ltp}</Text>
</View>
))}
</ScrollView>
</View>
);
}));
export default React.memo(Deplyee);

I was to implement CustomPicker in my functional component in react native

Please tell me that
if I want to change the CustomExample Class component into a functional component
**as: ** const CustomExample = () =>{...}
then how will change the following code to work in similar manner:
<CustomPicker
placeholder={'Please select your favorite item...'}
options={options}
getLabel={item => item.label}
fieldTemplate={this.renderField}
optionTemplate={this.renderOption}
/>
I have tried following methods:
changing definition as
rederField(settings){...} to const renderField = (settings) => {...}
and then assigning renderField to fieldTemplate as follow:
* fieldTemplate={renderField()}
* fieldTemplate={()=>renderField()}
* fieldTemplate={renderField(selectedItem,defaultText,getLabel,clear)}
on each attempt it showed some error.
PLZ HELP ME I'M STUCK ON IT FROM LAST FEW DAYS
GOING THROUGH ALL THE DOCS WILL TAKE MONTHS FOR ME.
import * as React from 'react'
import { Alert, Text, View, TouchableOpacity, StyleSheet } from 'react-native'
import { CustomPicker } from 'react-native-custom-picker'
export class CustomExample extends React.Component {
render() {
const options = [
{
color: '#2660A4',
label: 'One',
value: 1
},
{
color: '#FF6B35',
label: 'Two',
value: 2
},
]
return (
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center' }}>
<CustomPicker
placeholder={'Please select your favorite item...'}
options={options}
getLabel={item => item.label}
fieldTemplate={this.renderField}
optionTemplate={this.renderOption}
/>
</View>
)
}
renderField(settings) {
const { selectedItem, defaultText, getLabel, clear } = settings
return (
<View style={styles.container}>
<View>
{!selectedItem && <Text style={[styles.text, { color: 'grey' }]}>{defaultText}</Text>}
{selectedItem && (
<View style={styles.innerContainer}>
<TouchableOpacity style={styles.clearButton} onPress={clear}>
<Text style={{ color: '#fff' }}>Clear</Text>
</TouchableOpacity>
<Text style={[styles.text, { color: selectedItem.color }]}>
{getLabel(selectedItem)}
</Text>
</View>
)}
</View>
</View>
)
}
renderOption(settings) {
const { item, getLabel } = settings
return (
<View style={styles.optionContainer}>
<View style={styles.innerContainer}>
<View style={[styles.box, { backgroundColor: item.color }]} />
<Text style={{ color: item.color, alignSelf: 'flex-start' }}>{getLabel(item)}</Text>
</View>
</View>
)
}
}
// STYLE FILES PRESENT HERE.
change the definition of function to
function renderOption(settings) {...}
function renderField (settings) {...}
and call function like this.
<CustomPicker
placeholder={'Please select your favorite item...'}
options={options}
getLabel={item => item.label}
fieldTemplate={renderField}
optionTemplate={renderOption}
/>

TypeError: in props.onStartGame(selectedNumber) , 'props.onStartGame' is undefined

I am following this module on Alex Macmillian's Udemy COurse on react native:
In the 65th module, I am getting this error :
error screenshot
import React, { useState } from "react";
import {
View,
StyleSheet,
Text,
TouchableWithoutFeedback,
Keyboard,
Dimensions,
Alert,
TouchableOpacity,
} from "react-native";
import Card from '../components/Card'
import Colors from '../constants/Colors'
import Input from '../components/Input'
import CircleShape from '../components/CircleShape'
import HeartShape from '../components/HeartShape'
import CrossShape from '../components/CrossShape'
const StartGameScreen = props => {
const [enteredValue, setEnteredValue] = useState('')
const [selectedNumber, setSelectedNumber] = useState()
const [confirmed, setConfirmed] = useState(false);
//validates the non valid inputs in the inputText
const changeTextHandler = inputText => {
//replaces any character other than 0-9 with a blank
setEnteredValue(inputText.replace(/[^0-9]/g, ''))
}
const resetInputHandler = () => {
setEnteredValue('');
Keyboard.dismiss()
setConfirmed(false)
}
const confirmInputHandler = () => {
const chosenNumber = parseInt(enteredValue);
if (isNaN(chosenNumber) || chosenNumber <= 0 || chosenNumber > 99) {
Alert.alert('Invalid String!', "Enter a number between 0 and 99",
[{ text: "Okay", style: "default", onPress: resetInputHandler },
{ text: 'Cancel', style: 'destructive', onPress: resetInputHandler }])
return;
}
setConfirmed(true);
setSelectedNumber(chosenNumber)
setEnteredValue('')
Keyboard.dismiss()
}
let confirmedOutput;
if (confirmed) {
// confirmedOutput = <Text> You Chose : {selectedNumber} </Text>
confirmedOutput = (
<Card style={styles.circleShapeView}>
<Text style={styles.selectedNumber}>{selectedNumber}</Text>
<TouchableOpacity
activeOpacity={0.26}
style={styles.TriangleShapeView}
onPress={() => props.onStartGame(selectedNumber)}>
</TouchableOpacity>
</Card>
)
}
return (
<TouchableWithoutFeedback onPress={() => {
Keyboard.dismiss()
}}>
<View style={styles.screen}>
<Card style={styles.gameArea}>
<Input
style={styles.textInput}
keyboardType="numeric"
maxLength={2}
onChangeText={changeTextHandler}
value={enteredValue}
placeholder='0'
placeholderTextColor="#000" />
{/* <View style={styles.buttonContainer}>
<View style={styles.button}>
<Button
onPress={resetInputHandler}
title="Reset"
color="#fff" />
</View>
<View style={styles.button}>
<Button
title="Confirm"
color="#fff"
onPress={confirmInputHandler} />
</View>
</View> */}
<View style={styles.buttonContainer}>
<TouchableOpacity style={styles.heartButton} onPress={resetInputHandler}>
<CircleShape style={styles.circle}>
<HeartShape style={styles.heart}>
</HeartShape>
</CircleShape>
</TouchableOpacity>
<TouchableOpacity style={styles.crossButton} onPress={confirmInputHandler}>
<CircleShape style={styles.circle}>
<CrossShape style={styles.cross}></CrossShape>
</CircleShape>
</TouchableOpacity>
</View>
</Card>
{confirmedOutput}
</View>
</TouchableWithoutFeedback>
);
}
export default StartGameScreen;
The App.js file -->
import React, { useState } from 'react';
import { StyleSheet, View } from 'react-native';
import Header from './components/Header'
import StartGameScreen from './screens/StartGameScreen'
import GameScreen from './screens/GameScreen';
export default function App() {
const [userNumber, setUserNumber] = useState();
const startGameHandler = selectedNumber => {
setUserNumber(selectedNumber);
}
let screen = <StartGameScreen onStartGame={startGameHandler} />;
if (userNumber) {
screen = <GameScreen userChoice={userNumber}/>
}
return (
<View style={styles.screen}>
<Header title="Guessie"></Header>
<StartGameScreen></StartGameScreen>
</View>
);
}
const styles = StyleSheet.create({
screen: {
flex:1
},
});
How do i fix this error?
Type Error: props.onStartGame is not a function. (IN 'props.onStartGame(selectedNUmber)','props.onStartGame' is undefined)
You need to pass screen variable instead of <StartGameScreen></StartGameScreen> ,
if first approach doesn't work trying passing the onStartGame={startGameHandler} like this in your code <Header title="Guessie"></Header>
<StartGameScreen onStartGame={startGameHandler} >
</StartGameScreen>
if (isNaN(chosenNumber) || chosenNumber <= 0 || chosenNumber > 99) {
Alert.alert(
'Invalid number!',
'Number has to be a number between 1 and 99.',
[{ text: 'Okay', style: 'destructive', onPress: resetInputHandaler }]
);

React native flatlist, not expected behavior

Hi I am starting to use FlatList component instead of ListView and I am having some problems trying to render the separator, I made a multiple-choice component and it is working ok but I don't understand why it is not rendering the separator from the flatlist, if I put the separator inside the renderItem function it's working ok, but I want to use it from the flatlist as a prop.
One curious thing is if I delete the itemSeparatorComponent prop from the FlatList in render method the component stops updating the checkmark (renderIndicator()) that indicates that item is selected, so it's really annoying this, I put the whole code, please check it.
React native: 0.44.0
import React, { Component } from 'react';
import { Button, Icon, Divider } from 'react-native-elements';
import { FlatList, View, TouchableOpacity, Text } from 'react-native';
import { Card, CardSection } from './commons';
import { appMainColor } from '../constants';
export default class ListOrderItems extends Component {
static navigationOptions = {
title: 'Realice su selección'
};
state = { selected: [], items: this.props.navigation.state.params.items };
onItemPress = (item) => {
const selected = this.state.selected;
const index = selected.indexOf(item.name);
if (index === -1) {
selected.push(item.name);
} else {
selected.splice(index, 1);
}
this.setState({ selected });
};
isSelected = (item) => {
return this.state.selected.indexOf(item.name) !== -1;
};
keyExtractor = (item, index) => {
return index;
};
renderOkButton = () => {
if (this.props.navigation.state.params.type === 'multipleChoice') {
return (
<Button
raised
borderRadius={5}
backgroundColor={appMainColor}
title='Aceptar'
onPress={() => this.props.navigation.goBack()}
/>
);
}
};
renderCancelButton = () => {
return (
<Button
raised
borderRadius={5}
backgroundColor={appMainColor}
title='Cancelar'
onPress={() => this.props.navigation.goBack()}
/>
);
};
renderIndicator = (item) => {
if (this.isSelected(item)) {
return <Icon name="check-circle" color={appMainColor} />;
}
};
renderSeparator = () => {
return <Divider />;
};
renderItem = ({ item, index }) => {
return (
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.onItemPress(item, index)}
>
<View style={styles.row}>
<View style={styles.optionLabel}>
<Text>{item.name} (${item.price})</Text>
</View>
<View style={styles.optionIndicator}>
{this.renderIndicator(item, index)}
</View>
</View>
</TouchableOpacity>
);
};
render() {
return (
<View>
<Card>
<CardSection>
<FlatList
data={this.state.items}
keyExtractor={this.keyExtractor}
renderItem={this.renderItem}
itemSeparatorComponent={() => this.renderSeparator()}
/>
</CardSection>
</Card>
<Card>
<CardSection style={{ justifyContent: 'space-around' }}>
{this.renderOkButton()}
{this.renderCancelButton()}
</CardSection>
</Card>
</View>
);
}
}
const styles = {
row: {
flexDirection: 'row',
padding: 5
},
optionLabel: {
flex: 1,
},
optionIndicator: {
width: 30,
height: 30,
justifyContent: 'center',
alignItems: 'center'
}
};
I think you made some typo, it should be ItemSeparatorComponent, not itemSeparatorComponent.
Flatlist list items are pure components if you want to check with are selected you should set this in the data source you pass in. Otherwise, the props for the item remain the same and the component will not rerender.
For the divider can you try itemSeparatorComponent={Divider}

Categories