How to send value with react-navigation in static filed? - react-native

I have a screen set a <Switch /> in header by using react navigation.
I know how to get this.state value from outside function by this.props.navigation.setParams.
But I don't know how to send the <Switch /> value to outside function.
I try it with the code onValueChange={value => params.handleThis(value)}
but in my case handleThis is key-value, it can't get the value obviously.
this.props.navigation.setParams({
handleThis: this.changeSwitch
});
How to send <Switch /> onChange value to outside function ?
Here is my code:
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
title: 'Title',
headerStyle: {
backgroundColor: ColorSetting.headerColor,
elevation: null,
},
headerTitleStyle: {
fontWeight: '300',
fontFamily: 'FFF Tusj',
fontSize: 18
},
headerRight:
<View style={{ marginRight: 15 }}>
<Switch
onValueChange={value => params.handleThis()}
value={params.switchOn}
onTintColor='#444444'
tintColor='#444444'
/>
</View>,
};
};
constructor(props) {
super(props);
this.state = {
switchOn: false
};
}
componentDidMount() {
this.props.navigation.setParams({
handleThis: this.changeSwitch
});
}
changeSwitch = () => {
const { switchOn, titleVersion } = this.state;
this.props.navigation.setParams({ switchOn: !switchOn });
this.setState({ switchOn: !switchOn });
}
Any help would be appreciated. Thanks in advance.

You can use params.handleThis as the handler, there is no need for an inline function.
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
title: 'SO Question',
headerStyle: {
elevation: null,
},
headerTitleStyle: {
fontFamily: 'FFF Tusj',
fontSize: 18
},
headerRight:
<View style={{ marginRight: 15 }}>
<Switch
onValueChange={params.handleThis}
value={params.switchOn}
onTintColor='#444444'
tintColor='#444444'
/>
</View>,
};
};
after that changeSwitch will receive the new value as the first parameter.
changeSwitch = (switchOn) => {
this.props.navigation.setParams({ switchOn });
this.setState({ switchOn });
}
Here's a working example

Related

Header is not visible in react native

import React, {Component} from 'react';
import {Text, View,TextInput,Button,Alert,KeyboardAvoidingView,ScrollView,Dimensions,TouchableOpacity} from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
import {BoxShadow} from 'react-native-shadow'
import DropdownAlert from 'react-native-dropdownalert';
import datum from './data';
import Parse from "parse/react-native";
export default class Editprofile extends React.Component {
static navigationOptions = {
title: 'Edit Profile',
headerStyle: {
backgroundColor:'#E8EDF1',
},
headerTintColor:datum.primaryColor,
headerTitleStyle: {
fontWeight: 'bold',
textAlign:"center",
flex:1
},
};
constructor(props) {
super(props)
this.state = {name:"",number:0,windowwidth:Dimensions.get('window').width,windowheight:Dimensions.get('window').height,custid:""};
}
componentDidMount() {
Parse.setAsyncStorage(AsyncStorage);
getData = async () => {
try {
const value = await AsyncStorage.getItem('nameKey')
if(value !== null) {
this.setState({name:await AsyncStorage.getItem('nameKey')
,number: await AsyncStorage.getItem('numberKey')})
const GameScore = Parse.Object.extend("Customer");
const query = new Parse.Query(GameScore);
query.equalTo("phonenumber",parseInt(this.state.number));
const results = await query.find();
for (let i = 0; i < results.length; i++) {
var object = results[i];
this.setState({custid:JSON.stringify(object.id)})
}
}
} catch(e) {
this.dropdown.alertWithType('error', 'Error', 'Error reading values');
}
}
getData();
}
updatedata = async () => {
try {
await AsyncStorage.setItem('nameKey',this.state.name)
await AsyncStorage.setItem('numberKey',this.state.number)
var P = Parse.Object.extend("Customer");
var instance = new P();
var temp=this.state.custid.replace(/['"]+/g, '')
var temptwo=temp.replace(/\//g, "")
instance.id = temptwo.replace(/['"]+/g, '')
instance.set("name",this.state.name);
instance.set("phonenumber",parseInt(this.state.number));
instance.save();
this.dropdown.alertWithType('success', 'Success', 'saved locally ');
} catch (e) {
this.dropdown.alertWithType('error', 'Error', 'Cannot able to create profile');
}
}
render() {
const shadowOpt = {
width:this.state.windowwidth*0.5,
height:this.state.windowheight*0.07,
color:"#000",
border:26,
radius:3,
opacity:0.2,
x:0,
y:3,
style:{marginVertical:5}
}
return (
<View style={{flex:1,flexDirection:'column',justifyContent:'space-evenly',alignItems:'center',backgroundColor:'#E8EDF1'}}>
<BoxShadow setting={shadowOpt}>
<TextInput
placeholderTextColor={datum.placeholderTextColor}
style={{
height: this.state.windowheight*0.07, borderColor:datum.primaryColor, borderWidth: 1,
width:this.state.windowwidth*0.5,backgroundColor:datum.primaryColor, fontWeight: '200',elevation: 2
}}
onChangeText={(value) => this.setState({name:value.trim()})}
value={this.state.name}
/>
</BoxShadow>
<BoxShadow setting={shadowOpt}>
<TextInput
placeholderTextColor={datum.placeholderTextColor}
keyboardType='number-pad'
style={{height: this.state.windowheight*0.07, borderColor:datum.primaryColor, borderWidth: 1,width:this.state.windowwidth*0.5,backgroundColor:datum.primaryColor, fontWeight: '200'}}
onChangeText={(value) => this.setState({number:value})}
value={this.state.number}
/>
</BoxShadow>
<BoxShadow setting={shadowOpt}>
<Button
onPress={()=>this.updatedata()
}
title="Signup"
color={datum.primaryColor}
accessibilityLabel="Learn more about this purple button"
/>
</BoxShadow>
<DropdownAlert ref={ref => this.dropdown = ref} />
</View>
);
}
}
I am using drawer navigation in this project but I don't understand why the header is not visible in my project it is blank, can someone say how to add a header to my component so that I can run out of complaints, I am struggling with this error for past two weeks
react-natvigation is used in the project ,
my app.js
const MyDrawerNavigator = createDrawerNavigator({
entry:{
screen:SIgnup,
navigationOptions: {
drawerLabel: () => null
},
},
Home: {
screen: HOme,
navigationOptions: {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<Image
source={require("./components/Drawbles/Homeicon.png")}
resizeMode="contain"
style={{ width: 20, height: 20 }}
/>
)
}
},
Editprofile: {
screen: EDit,
navigationOptions: {
drawerLabel: 'Edit Profile',
drawerIcon: ({ tintColor }) => (
<Image
source={require("./components/Drawbles/EditProfile.png")}
resizeMode="contain"
style={{ width: 20, height: 20, tintColor: tintColor }}
/>
)
}
},
Offerrides: {
screen: OFferrides,
navigationOptions: {
drawerLabel: 'Offer Rides',
drawerIcon: ({ tintColor }) => (
<Image
source={require("./components//Drawbles/Offerride.png")}
resizeMode="contain"
style={{ width: 20, height: 20 }}
/>
)
}
},
Paymentmethod: {
screen: PAymentmethod,
navigationOptions: {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<Image
source={require("./components/Drawbles/Paymentmethod.png")}
resizeMode="contain"
style={{ width: 20, height: 20 }}
/>
)
}
},
Otp: {
screen: OTp,
navigationOptions: {
drawerLabel: () => null //hide header if not needed so whole screen slide
},
}
},{});
const MyApp = createAppContainer(MyDrawerNavigator);
export default MyApp;
Drawer navigation by default doesn't display the header,it just display the drawing menu. As it is you can open the drawer by sliding right,if you want to open it with a header you have to do a component and use it on screens you want. Heres a nice example of headers: https://react-native-training.github.io/react-native-elements/docs/header.html
Try change this:
static navigationOptions = {
...props...
}
To this:
static navigationOptions = () => {
return {
...props...
}
}

React Native button error problem, cant have click listener

When pressing the Button nothing happens. The picture shows a warning and I can get rid of that if I change the
onPress={this._onSearchPressed}
to
onPress={() => this._onSearchPressed()}
But now when pressing the Button i get the error you see on the picture below like "undefined is not a function..".
How do I call a onPress correctly?
'use strict';
import React, { Component } from 'react';
import {
StyleSheet,
Text,
TextInput,
View,
Button,
ActivityIndicator,
Image,
} from 'react-native';
type Props = {};
function urlForQueryAndPage(key, value, pageNumber) {
const data = {
country: 'uk',
pretty: '1',
encoding: 'json',
listing_type: 'buy',
action: 'search_listings',
page: pageNumber,
};
data[key] = value;
const querystring = Object.keys(data)
.map(key => key + '=' + encodeURIComponent(data[key]))
.join('&');
return 'https://api.nestoria.co.uk/api?' + querystring;
}
export default class SearchPage extends Component<Props> {
static navigationOptions = {
title: 'Property Finder',
};
constructor(props) {
super(props);
this.state = {
searchString: 'london',
isLoading: false,
};
}
_onSearchTextChanged = (event) => {console.log('_onSearchTextChanged');
this.setState({ searchString: event.nativeEvent.text });
console.log('Current: '+this.state.searchString+', Next: '+event.nativeEvent.text);
_executeQuery = (query) => {
console.log(query);
this.setState({ isLoading: true });
};
_onSearchPressed = () => {
const query = urlForQueryAndPage('place_name', this.state.searchString, 1);
this._executeQuery(query);
};
};
render() {
console.log('SearchPage.render');
const spinner = this.state.isLoading ? <ActivityIndicator size='large'/> : null;
return (
<View style={styles.container}>
<Text style={styles.description}>
Search for houses to buy!
</Text>
<Text style={styles.description}>
Search by place-name or postcode.
</Text>
<View style={styles.flowRight}>
<TextInput
underlineColorAndroid={'transparent'}
style={styles.searchInput}
value={this.state.searchString}
onChange={this._onSearchTextChanged}
placeholder='Search via name or postcode'/>
<Button
onPress={this._onSearchPressed}
color='#48BBEC'
title='Go'>
</Button>
</View>
<Image source={require('./Resources/house.png')} style={styles.image}/>
{spinner}
</View>
);
}
}
const styles = StyleSheet.create({
description: {
marginBottom: 20,
fontSize: 18,
textAlign: 'center',
color: '#a56565'
},
flowRight: {
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'stretch',
},
searchInput: {
height: 36,
padding: 4,
marginRight: 5,
flexGrow: 1,
fontSize: 18,
borderWidth: 1,
borderColor: '#48BBEC',
borderRadius: 8,
color: '#48BBEC',
},
container: {
padding: 30,
marginTop: 65,
alignItems: 'center'
},
image: {
width: 217,
height: 138,
},
});
Okay, I think I might have found the error.
Here inside your code
_onSearchTextChanged = (event) => {console.log('_onSearchTextChanged');
this.setState({ searchString: event.nativeEvent.text });
console.log('Current: '+this.state.searchString+', Next: '+event.nativeEvent.text);
_executeQuery = (query) => {
console.log(query);
this.setState({ isLoading: true });
};
_onSearchPressed = () => {
const query = urlForQueryAndPage('place_name', this.state.searchString, 1);
this._executeQuery(query);
};
};
You are nesting these two functions
_executeQuery = (query) => {
console.log(query);
this.setState({ isLoading: true });
};
_onSearchPressed = () => {
const query = urlForQueryAndPage('place_name', this.state.searchString, 1);
this._executeQuery(query);
};
inside your _onSearchTextChanged function. You probably might want to do something like this
_onSearchTextChanged = (event) => {console.log('_onSearchTextChanged');
this.setState({ searchString: event.nativeEvent.text });
console.log('Current: '+this.state.searchString+', Next: '+event.nativeEvent.text);
}
_executeQuery = (query) => {
console.log(query);
this.setState({ isLoading: true });
};
_onSearchPressed = () => {
const query = urlForQueryAndPage('place_name', this.state.searchString, 1);
this._executeQuery(query);
};
Notice the closing } of your first function

How to put this.props data into headerRight selector?

I use react-redux to get my FlatList data and custom my header with react-navigation.
I want to add a selector in headerRight, my problem is I have no idea how to add the data into my headerRight.
Here is my header setting.
const data = [
{ key: 0, section: true, label: 'Title' },
{ key: 1, label: 'Red Apples' },
{ key: 2, label: 'Cherries' },
{ key: 3, label: 'Cranberries', accessibilityLabel: 'Tap here for cranberries' },
{ key: 4, label: 'Vegetable', customKey: 'Not a fruit' }
];
class MovieTimeList extends Component {
static navigationOptions = ({ navigation }) => ({
title: `${navigation.state.params.theaterCn}`,
headerStyle: {
backgroundColor: '#81A3A7',
elevation: null,
},
headerTitleStyle: {
fontWeight: '300',
fontFamily: 'FFF Tusj',
fontSize: 18
},
headerRight:
<ModalSelector
data={data}
initValue="Title"
onChange={(option)=>{ alert(`${option.label} (${option.key}) nom nom nom`) }}
/>,
});
Here is my react-redux mapStateToProps function that action is call an API to get the data:
const mapStateToProps = (state) => {
const timeList = state.listType.timeList;
return { timeList };
};
I can show the movieData in FlatList from react-redux:
render() {
const movieData = this.props.timeList;
return (
<View style={{ flex: 1 }}>
<FlatList
data={movieData}
renderItem={this.renderRow}
horizontal={false}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
I have no idea how to let the const movieData into my headerRight selector.
Any help would be appreciated. Thanks in advance.
You can set param and then use it in your header like this
componentWillReceiveProps(nextProp){
if(!isFetching && listNotUpdated){
this.props.navigation.setParams({ movieList: nextProp.timeList})
}
}
then get it in the header like this
static navigationOptions = ({ navigation }) => {
const { state } = navigation
const { movieList }= navigation.state.params
return {
title: 'Your Title',
headerRight: (
<Button
title={'Button1'}
onPress={() => {
// do something
}}
/>
),
}
}
I am not sure if this code is 100% correct, basically, you can do it by connecting ur reducer to your MovieTimeList class pass necessary prop to your component
class MovieTimeList extends Component {
static navigationOptions = ({ navigation }) => ({
title: `${navigation.state.params.theaterCn}`,
headerStyle: {
backgroundColor: '#81A3A7',
elevation: null,
},
headerTitleStyle: {
fontWeight: '300',
fontFamily: 'FFF Tusj',
fontSize: 18
},
headerRight:
<ModalSelector
data={data}
initValue={this.props.HeaderTitle}
onChange={(option)=>{ alert(`${option.label} (${option.key}) nom nom nom`) }}
/>,
});
const mapStateToProps = (state) => {
let HeaderTitle = state.yourreducer.headerTitle
return HeaderTitle
}
export default connect(mapStateToProps,null)(MovieTimeList)

React Native - Conditional Back Button Based on State

Below is a simple example of what I'm trying to do. I have headerLeft in the navigation bar, but would like to make that disappear (so the user can't click back) when the user clicks the button (Take the Challenge) and thereby sets the state variable 'next' to true. Is this possible to do? If so, any suggestions on how?
export default class Challenge extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: "5 Day Challenge",
headerTintColor: "white",
headerStyle: { backgroundColor: "black" },
headerTitleStyle: { fontWeight: "bold", fontSize: moderateScale(15) },
headerLeft: (
<Button onPress={() => navigation.goBack(null)}>
{" "}
<MaterialCommunityIcons
name="arrow-left"
size={28}
/>
</Button>
)
});
constructor(props) {
super(props);
this.state = {
next: false,
};
}
render() {
return (
<View>
<Button
onPress={() =>
this.setState({ next: true })}
>
<Text >
TAKE THE CHALLENGE
</Text>
</Button>
</View>
)}
}
You can use the this.props.navigation.setParams({...});
export default class Challenge extends React.Component {
static navigationOptions = ({ navigation }) => {
const { state } = navigation;
if (state.params !== undefined) {
return {
title: "5 Day Challenge",
headerTintColor: "white",
headerStyle: { backgroundColor: "black" },
headerTitleStyle: { fontWeight: "bold", fontSize: moderateScale(15) },
headerLeft: state.params.showBack ? (
<Button onPress={() => navigation.goBack(null)}>
{" "}
<MaterialCommunityIcons
name="arrow-left"
size={28}
/>
</Button>
) : null
}
}
};
constructor(props) {
super(props);
this.state = {
next: false,
};
}
componentDidMount() {
this.props.navigation.setParams({
showBack: true
});
}
onClick = () => {
this.setState({ next: true })
this.props.navigation.setParams({
showBack: false
});
}
render() {
return (
<View>
<Button
onPress={() => this.onClick()} >
<Text >
TAKE THE CHALLENGE
</Text>
</Button>
</View>
)
}
}
PS : I hope it will work, I didn't test that code.

Setting styles to a custom component inside navigationOption in react native

I want to set styling for a custom component, inside navigationOptions in react native. But the stying doesnt work and it give an error saying. Same styling is working in another text box of the same screen.
P:S: I could achieve this by doing this? Am I doing this correct? Is this the proper way of handling this?
class WorkoutScreen extends Component {
constructor(props) {
super(props);
this.state = {
searchText: ""
};
}
componentDidMount() {
this.props.navigation.setParams({
searchWorkouts: this.searchWorkoutHandler,
onChangeSearchText: this.onChangeSearchTextHandler,
searchText: this.state.searchText
});
}
// on change search text
onChangeSearchTextHandler = value => {
this.setState({
searchText: value
});
this.props.navigation.setParams({
searchText: value
});
};
// search workouts
searchWorkoutHandler = () => {
alert("Searching Workouts");
};
render() {
return (
<View style={styles.container}>
<Text>Im Here</Text>
</View>
);
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
headerTitle: (
<SearchInput
style={styles.searchInput}
value={params.searchText}
source={Search}
borderRadius={50}
placeholder="Search / Filter"
onChangeText={value => params.onChangeSearchText(value)}
onPress={() => params.searchWorkouts()}
/>
),
headerTitleStyle: { width: "100%", alignItems: "center" },
headerStyle: {
paddingRight: 10,
paddingLeft: 10
},
headerLeft: (
<ClickableIcon
source={Bookmark}
onIconPressed={() => alert("Notifications Clicked Workout")}
/>
),
headerRight: (
<ClickableIcon
source={Movements}
onIconPressed={() => alert("Add New Clicked")}
/>
)
};
};
}
const styles = StyleSheet.create({
container: {
flex: 1
},
scrollView: {
backgroundColor: "#ffffff"
},
searchInput: {
height: 45,
color: "gray",
fontSize: 18
}
});
export default WorkoutScreen;
How can I overcome this?