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}
/>
Related
In my containerTop, I am rendering a list inside TripOptionsSelectorthat hides towards the end.
I have tried adding marginBottom/paddingBottom to containerOptionsSelectorbut it makes no difference. I don't want to add a height to my because it can vary according to different phones.
How else can I simply extend the View such that the text doesn't hide?
export const MapScreen: React.FunctionComponent = () => {
return (
<SafeAreaView style={styles.safeAreaViewContainer}>
<View style={styles.container}>
<View style={styles.containerTop}>
<BackArrow />
<JourneyLocationsTextContainer />
<View style={styles.containerOptionsSelector}>
<TripOptionsSelector />
</View>
</View>
<View style={styles.containerMap}>
<MapContainer />
<ButtonsContainer />
</View>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
safeAreaViewContainer: { flex: 1 },
container: { flex: 1, backgroundColor: 'white'},
containerTop: { flex: 1, backgroundColor: '#323443' },
containerOptionsSelector: {
marginTop: moderateScale(15),
marginLeft: moderateScale(20),
},
containerMap: {
flex: 2
},
});
export const TripOptionsSelector: React.FunctionComponent = () => {
return (
<View style={styles.offerContainer}>
<Text style={styles.offerText}>Jetzt</Text>
<Text style={styles.offerText}>1 Person</Text>
<Text style={styles.offerText} >Filter</Text>
</View>
);
};
const styles = StyleSheet.create({
offerContainer: {
flexDirection: 'row',
},
You just remove flex from styles.containerTop - so it's sized based purely on its content.
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>
)
}
Here, I am fetching data from firebase and then trying to output it in a tinder card like format. My code is as follows -
import React from 'react';
import { View, ImageBackground, Text, Image, TouchableOpacity } from 'react-native';
import CardStack, { Card } from 'react-native-card-stack-swiper';
import City from '../components/City';
import Filters from '../components/Filters';
import CardItem from '../components/CardItem';
import styles from '../assets/styles';
import Demo from '../assets/demo';;
import {db} from '../config/config';
class Home extends React.Component {
constructor (props) {
super(props);
this.state = ({
items: [],
isReady: false,
});
}
componentWillMount() {
let items = [];
db.ref('cards').once('value', (snap) => {
snap.forEach((child) => {
let item = child.val();
item.id = child.key;
items.push({
name: child.val().pet_name,
description: child.val().pet_gender,
pet_age: child.val().pet_age,
pet_breed: child.val().pet_breed,
photoUrl: child.val().photoUrl,
});
});
//console.log(items)
this.setState({ items: items, isReady: true });
console.log(items);
});
}
componentWillUnmount() {
// fix Warning: Can't perform a React state update on an unmounted component
this.setState = (state,callback)=>{
return;
};
}
render() {
return (
<ImageBackground
source={require('../assets/images/bg.png')}
style={styles.bg}
>
<View style={styles.containerHome}>
<View style={styles.top}>
<City />
<Filters />
</View>
<CardStack
loop={true}
verticalSwipe={false}
renderNoMoreCards={() => null}
ref={swiper => {
this.swiper = swiper
}}
>
{this.state.items.map((item, index) => (
<Card key={index}>
<CardItem
//image={item.image}
name={item.name}
description={item.description}
actions
onPressLeft={() => this.swiper.swipeLeft()}
onPressRight={() => this.swiper.swipeRight()}
/>
</Card>
))}
</CardStack>
</View>
</ImageBackground>
);
}
}
export default Home;
I am fetching data and storing it in an array called items[]. Console.log(items) gives me the following result:
Array [
Object {
"description": "male",
"name": "dawn",
"pet_age": "11",
"pet_breed": "golden retriever",
"photoUrl": "picture",
},
Object {
"description": "Male",
"name": "Rambo",
"pet_age": "7",
"pet_breed": "German",
"photoUrl": "https://firebasestorage.googleapis.com/v0/b/woofmatix-50f11.appspot.com/o/pFkdnwKltNVAhC6IQMeSapN0dOp2?alt=media&token=36087dae-f50d-4f1d-9bf6-572fdaac8481",
},
]
Furthermore, I want to output my data in a card like outlook so I made a custom component called CardItem:
import React from 'react';
import styles from '../assets/styles';
import { Text, View, Image, Dimensions, TouchableOpacity } from 'react-native';
import Icon from './Icon';
const CardItem = ({
actions,
description,
image,
matches,
name,
pet_name,
pet_gender,
pet_age,
onPressLeft,
onPressRight,
status,
variant
}) => {
// Custom styling
const fullWidth = Dimensions.get('window').width;
const imageStyle = [
{
borderRadius: 8,
width: variant ? fullWidth / 2 - 30 : fullWidth - 80,
height: variant ? 170 : 350,
margin: variant ? 0 : 20
}
];
const nameStyle = [
{
paddingTop: variant ? 10 : 15,
paddingBottom: variant ? 5 : 7,
color: '#363636',
fontSize: variant ? 15 : 30
}
];
return (
<View style={styles.containerCardItem}>
{/* IMAGE */}
<Image source={image} style={imageStyle} />
{/* MATCHES */}
{matches && (
<View style={styles.matchesCardItem}>
<Text style={styles.matchesTextCardItem}>
<Icon name="heart" /> {matches}% Match!
</Text>
</View>
)}
{/* NAME */}
<Text style={nameStyle}>{name}</Text>
{/* DESCRIPTION */}
{description && (
<Text style={styles.descriptionCardItem}>{description}</Text>
)}
{/* STATUS */}
{status && (
<View style={styles.status}>
<View style={status === 'Online' ? styles.online : styles.offline} />
<Text style={styles.statusText}>{pet_age}</Text>
</View>
)}
{/* ACTIONS */}
{actions && (
<View style={styles.actionsCardItem}>
<View style={styles.buttonContainer}>
<TouchableOpacity style={[styles.button, styles.red]} onPress={() => {
this.swiper.swipeLeft();
}}>
<Image source={require('../assets/red.png')} resizeMode={'contain'} style={{ height: 62, width: 62 }} />
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.orange]} onPress={() => {
this.swiper.goBackFromLeft();
}}>
<Image source={require('../assets/back.png')} resizeMode={'contain'} style={{ height: 32, width: 32, borderRadius: 5 }} />
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.green]} onPress={() => {
this.swiper.swipeRight();
}}>
<Image source={require('../assets/green.png')} resizeMode={'contain'} style={{ height: 62, width: 62 }} />
</TouchableOpacity>
</View>
</View>
)}
</View>
);
};
export default CardItem;
The problem is when I try to pass the data in my items[] array, the cardItem component just doesnt work. To dry-run, I used a sample demo array and when I use the Demo array, my component works just fine. What am I doing wrong? I have been tinkering with this problem for quite a while now. Any help whatsoever would be appreciated.
Disclaimer: Pretty novice in javascripting and react-native :)
I am trying a very simple application in react native. User is presented with a screen where two numbers and an operator is given (like +, - etc) and user will enter result in the text field provided. As in the screenshot below
To facilitate the application I have two main classes:
1) Parent Class (which basically generate the numbers, pass to the child as props, gets the result in callback function and if result is correct regenerates the numbers again)
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
View,
Text,
Button
} from 'react-native';
import BasicBox from '../components/BasicBox';
export default class example extends Component {
constructor() {
super();
this.state = {
result: 0
};
this.generate()
}
getResponse(result){
let text=""
for (var i = 0; i < result.length; i++) {
text += result[i];
}
console.log(result)
if (this.expected_result === parseInt(text))
{
this.generate()
}
this.setState({result:parseInt(text)})
}
generate() {
this.length = 3
this.number_1 = Math.floor(Math.random() * 1000)
this.number_2 = Math.floor(Math.random() * 1000)
this.result_box_count = this.length + 1
this.operator="+"
this.expected_result = eval (this.number_1 + this.operator + this.number_2)
console.log(this.number_1)
console.log(this.number_2)
console.log(this.expected_result)
// this.setState({result:this.expected_result})
}
render() {
//this.generate();
return (
<View>
<BasicBox
number_1={this.number_1}
number_2={this.number_2}
operator={this.operator}
result_box_count={this.result_box_count}
get_result = {this.getResponse.bind(this)}
/>
<Text>
{console.log(this.expected_result)}
{console.log(this.state.result)}
{this.state.result===this.expected_result ? "": "Oh Boy!" }
</Text>
</View>
);
}
}
2) child class (which takes numbers generated from parent, and returns the result to parent, on button press)
import React, { Component } from 'react';
import {Text, TextInput, Image, View, StyleSheet, Button} from "react-native"
export default class BasicBox extends Component {
constructor() {
super();
this.state = {
result: ["","","",""]
};
}
render(){
return (<View>
<View style={styles.main}>
<View>
<View style={styles.operand}>
<Text style={styles.digit}>{Math.floor(this.props.number_1/100)}</Text>
<Text style={styles.digit}>{Math.floor(this.props.number_1/10%10)}</Text>
<Text style={styles.digit}>{this.props.number_1%10}</Text>
</View>
<View style={styles.operand}>
<Text style={styles.digit}>{Math.floor(this.props.number_2/100)}
</Text>
<Text style={styles.digit}>{Math.floor(this.props.number_2/10%10)}</Text>
<Text style={styles.digit}>{this.props.number_2%10}</Text>
</View>
<View style={styles.operand}>
<View>
<Text style={styles.digit_hidden} >1</Text>
<TextInput style={styles.digit_answer}
keyboardType='numeric'
maxLength={1}
onChangeText={(txt)=>{
result=this.state.result;
result[0]=txt
this.setState({result:result})
}}
>
</TextInput>
</View>
<View>
<Text style={styles.digit_hidden}>1</Text>
<TextInput style={styles.digit_answer}
keyboardType='numeric'
maxLength={1}
onChangeText={(txt)=>{
result=this.state.result;
result[1]=txt
this.setState({result:result})
}
}
>
</TextInput>
</View>
<View>
<Text style={styles.digit_hidden}>1</Text>
<TextInput style={styles.digit_answer}
keyboardType='numeric'
maxLength={1}
onChangeText={(txt)=>{
result=this.state.result;
result[2]=txt,
this.setState({result:result})
}}
></TextInput>
</View>
<View>
<Text style={styles.digit_hidden}>1</Text>
<TextInput style={styles.digit_answer}
keyboardType='numeric' maxLength={1}
onChangeText={(txt)=>{
result=this.state.result;
result[3]=txt,
this.setState({result:result})
}}
></TextInput>
</View>
</View>
</View>
<View>
<Text style={styles.digit}>{this.props.operator}</Text>
</View>
</View>
<Button onPress={()=>{this.props.get_result(this.state.result)}}
title="Check Result"
/>
</View>)
}
}
const styles = StyleSheet.create ({
main: {
flexDirection:"row",
// borderWidth:1,
// flex: 1,
justifyContent: "center",
// alignItems: "center"
},
digit: {
fontSize: 80,
// borderWidth:1,
//adjustsFontSizeToFit
},
digit_hidden: {
fontSize: 80,
// borderWidth:1,
flex:1,
// color: `rgb(255,255,255)`
},
operand: {
flexDirection:"row",
justifyContent:"flex-end",
// alignItems:"flex-end",
// borderWidth:1,
},
digit_answer: {
// alignItems:"baseline",
// flexDirection:"row",
// justifyContent:"flex-end",
// backgroundColor: `rgb(255,255,255)`,
// alignItems:"flex-end",
fontSize: 80,
// backgroundColor: gray`rgb(255,255,255)`,
backgroundColor:'gray',
borderWidth:1,
},
});
Thank you for reading so far :)
In my class definitions, Button is in my child class because I want to send results to parent in OnPress. For UI My questions are:
1) Most importantly, How can I move the Button to my parent class and get the result somehow back to my parent from the child class?
2) My TextInput fields in < BasicBox> don't get cleared when numbers are regenerated. What's wrong here?
You need to use the UNSAFE_componentWillReceive method in child component when the parent component value changes
I am new to React Native I am making a sample app where the user can login and register for a new account.
I have two React classes,
One is the main class index.ios.js and another class called register.js. In the index class I am saying if the variable register is true render the register screen.
In the class register.js I am trying to set the variable register to false using this.setState({register:false}) but it is not causing the re render of the parent (index.ios.js). Is the a super(state) method or something similar that I am missing ? I believe the parent state is not getting the values of the updated register variable.
Here are my classes:
Render inside index.ios.js:
render: function() {
if(this.state.register) {
return this.renderRegisterScreen();
}
else if (this.state.loggedIn) {
return this.userLoggedIn();
}
else {
return this.renderLoginScreen();
}
}
Register.js:
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TouchableHighlight,
TextInput,
} = React;
var Register = React.createClass({
render: function() {
return (
<View style={styles.container}>
<View style={styles.rafitoImage}>
<Image source={require('./logo.png')}></Image>
<Text style={styles.slogan}>Eliminate the need to wait!</Text>
</View>
<View style={styles.bottomSection}>
<View style={styles.username}>
<View style={styles.inputBorder}>
<TextInput placeholder="Username..." style={styles.usernameInput} onChangeText={(text) => this.setState({username: text})}/>
</View>
<View style={styles.inputBorder}>
<TextInput password={true} placeholder="Password..." style={styles.usernameInput} onChangeText={(text) => this.setState({password: text})}/>
</View>
<View style={styles.inputBorder}>
<TextInput password={true} placeholder="Verify Password..." style={styles.usernameInput} onChangeText={(text) => this.setState({verifyPassword: text})}/>
</View>
<View style={styles.inputBorder}>
<TextInput placeholder="Phone.." style={styles.usernameInput} onChangeText={(text) => this.setState({phone: text})}/>
</View>
<View style={styles.inputBorder}>
<TextInput placeholder="Email.." style={styles.usernameInput} onChangeText={(text) => this.setState({email: text})}/>
</View>
<TouchableHighlight style={styles.button}
underlayColor='#f1c40f' onPress={this.register}>
<Text style={styles.buttonText}>Register</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.signUp} onPress={this.resetToLogin}
underlayColor='#ffffff'>
<Text style={styles.signUpText}>Already A Member </Text>
</TouchableHighlight>
</View>
</View>
<View style={styles.copyright}>
</View>
</View>
);
},
resetToLogin: function() {
this.setState({
register: false //I want this to re render the home screen with the variable register as false
});
}
});
var styles = StyleSheet.create({
container: {
flex : 1
},
bottomSection: {
flex: 5,
flexDirection: 'row'
},
button: {
height: 36,
backgroundColor: '#32c5d2',
justifyContent: 'center',
marginTop: 20
},
buttonText: {
fontSize: 18,
color: 'white',
alignSelf: 'center'
},
signUpText: {
color: '#3598dc'
},
signUp: {
alignItems: 'flex-end',
marginTop: 10,
},
username: {
flex: 1,
padding: 5
},
rafitoImage: {
flex: 3,
justifyContent: 'center',
alignItems: 'center',
},
copyright: {
alignItems: 'center'
},
usernameInput: {
height: 36,
marginTop: 10,
marginBottom: 10,
fontSize: 18,
padding: 5
},
copyrightText: {
color: '#cccccc',
fontSize: 12
},
inputBorder: {
borderBottomWidth: 1,
borderBottomColor: '#ececec'
},
slogan: {
color: '#3598dc'
}
});
module.exports = Register;
Attempt 1
As per the answer I added this to my index.ios.js
renderRegisterScreen: function() {
return (
<Register login={this.login}/>
)
}
And I added this to my register.js
<TouchableHighlight style={styles.signUp} onPress={this.props.login}
underlayColor='#ffffff'>
<Text style={styles.signUpText}>Already A Member </Text>
</TouchableHighlight>
But for some reason it does not even go to the register screen anymore, it executes the login function as soon as the register screen renders. What am I missing now ? Please advise.
Thanks
Update
It works when I pass down registered as a property but not when I do not. I would like to understand why if someone could post that.
Thanks
You can pass the function down to the child as props, then set the state of the parent from within the child that way.
Parent Component:
var Parent = React.createClass({
getInitialState() {
return {
registered: false
}
},
register(){
console.log("logging in... ");
this.setState({
registered: true
});
},
render: function() {
return (
<View style={styles.container}>
<Child register={this.register.bind(this)} registered={this.state.registered} />
{this.state.registered && <View style={{padding:10, backgroundColor:'white', marginTop:10}}>
<Text style={{fontSize:20}}>Congratulations, you are now registered!</Text>
</View>}
</View>
);
}
});
Child Component:
var Child = React.createClass({
render: function() {
return(
<View style={{backgroundColor: 'red', paddingBottom:20, paddingTop:20 }}>
<TouchableHighlight style={{padding:20, color: 'white', backgroundColor: 'black'}} onPress={() => this.props.register() }>
{this.props.registered ? <Text style={{color: 'white'}}>registered</Text> : <Text style={{color: 'white'}}>register</Text>}
</TouchableHighlight>
</View>
)
}
})
Here is a more powerful solution. This will let the child component change any state variable in the parent.
Parent component:
render: function() {
return (
...
<Child setParentState={newState=>this.setState(newState)} />
...
);
}
// Take note of the setState()
Child component:
this.props.setParentState({registered: true})
Why my attempt was failing was because I was using
onPress={this.props.login}
It should be
onPress={()=>this.props.login}
because of that mistake my onPress function would execute as soon as the button would render. I am not sure why that happens but I know what my mistake was.
Using StackNavigator I found a soultion leveraging screenProps. Here you can pass down functions and values to your routes. App global state is managed in App. App then passes in functions and/or state to NavComponent screenProps. Each child route in StackNavigator will then have access via this.props.screenProps
This solution is working well for now. Would love some feedback, or suggestions for improving this method
class HomeScreen extends React.Component {
render() {
return (
<View>
<Text>{JSON.stringify(this.props.screenProps.awesome)}</Text>
<Button
onPress={() => this.props.screenProps.updateGlobalState("data")}
title="Update parent State"
/>
</View>
);
}
}
const NavComponent = StackNavigator({
Home: { screen: HomeScreen },
// AllOthers: { screen: AllComponentsHereMayAccessScreenProps },
});
export default class App extends React.Component {
constructor() {
super();
this.state = {
everythingIsAwesome: false,
}
}
_updateGlobalState(payload) {
console.log('updating global state: ', payload);
this.setState({everythingIsAwesome: payload});
}
render() {
return <NavComponent screenProps={{
updateGlobalState: this._updateGlobalState.bind(this),
awesome: this.state.everythingIsAwesome
}} />;
}
}