I want to add a 'reload' button to my header, which I'm doing by calling setParams. Problem is that this causes the TabNavigator to navigate to the tab at launch
export default class FeedScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
const { params } = navigation.state;
if (params) {
return {
headerRight: <Icon.Button
color="black"
backgroundColor="transparent"
underlayColor="transparent"
name="reload"
onPress={ params.reload }
/>
};
}
}
constructor (props) {
super(props);
// We want to set attach a reload function to the navigation
this.props.navigation.setParams({
reload: this._reloadFeed.bind(this)
});
}
So is there a way setParams can not navigate to this scene, or is there a way to assign the function to this icon without calling setParams?
Have you tried setting onPress={ params.reload } to onPress={() => params.reload()}?
export default class FeedScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
const { params } = navigation.state;
if (params) {
return {
headerRight: <Icon.Button
color="black"
backgroundColor="transparent"
underlayColor="transparent"
name="reload"
onPress={ () => params.reload() } < -----
/>
};
}
}
constructor (props) {
super(props);
// We want to set attach a reload function to the navigation
this.props.navigation.setParams({
reload: this._reloadFeed.bind(this)
});
}
You are probably looking for Navigation Actions, specifically Navigation Action that is called "setParams" (do not confuse with navigation.setParams()), which you dispatch this way: navigation.dispatch(myCreatedSetParamsAction)
I was able to work around this by calling a static function from the header, and just updating that static function to my reload function in the componentDidMount. It's hacky but works.
Function outside my component:
let _reloadFunction = () => {
// This exists because react navigation is a mess
}
Navigation options
static navigationOptions = {
headerRight: <Icon.Button
color="black"
backgroundColor="transparent"
underlayColor="transparent"
name="reload"
onPress={() => { _reloadFunction() }}
/>
}
In the component:
// Gonna update that reloadFunction so the header works
_reloadFunction = this._reloadFeed.bind(this);
Related
I have only been working with React-Native recently. For this reason, I would need help with the following problem:
I did override the back button action in the header of a stack navigator, to navigate to any screen. I have to "send back" props to the screen xy. I have tried it on several variants, but unfortunately get error messages (because it does not work as I want) or do not get the expected result. I would be grateful for a solution. Thank you!
static navigationOptions = ({navigation}) => ({
title: null,
headerStyle: {backgroundColor: 'transparent'},
headerLeft: <HeaderBackButton
onPress={() => {
this.props.navigation.state.params.returnData(CurrentServiceProvider,'ServiceProvider')
navigation.push('digitalCode'),{ Info1: SomeObject, Info2: SomeObject }
}}
/>
})
Edit:
Screen B:
export class ScreenB extends React.Component {
static navigationOptions = ({navigation}) => ({
title: null,
headerStyle: {backgroundColor: 'transparent'},
headerLeft: <HeaderBackButton onPress={() => {
navigation.state.params.goBackData({SomeObject, 'ObjectIdentifier'});
navigation.push('ScreenA')}
}
/>
})
}
Screen A:
export class ScreenA extends React.Component {
getBackData = (data) => console.log(data)
ForwardNextScreen(){
this.props.navigation.navigate('ScreenB', {goBackData: this.getBackData});
}
}
If you want to send data back to previous screen ,the correct way is to declare callback on navigationParams (Github issue)
ScreenA
getBackData = (data) => console.log(data)
changeScreen = () => this.props.navigation.navigate('ScreenB', { goBackData: this.getBackData })
ScreenB
this.props.navigation.state.params.goBackData({
//your data json or whatever
})
this.props.navigation.pop()
Edit
Please change your from
headerLeft: <HeaderBackButton onPress={() => {
navigation.state.params.goBackData({SomeObject, 'ObjectIdentifier'});
navigation.push('ScreenA')}
}
/>
to
headerLeft: <HeaderBackButton onPress={() => {
navigation.getParam('goBackData')({SomeObject, 'ObjectIdentifier'});
navigation.pop();
}
/>
I want to set a custom navigation headerLeft property;How i can set the headerLeft property only if the condition is satisfied.otherwise not.I use a StackNavigator in my app. and also cannot access props from inside navigationOptions.
here is my code
componentDidMount() {
this.props.navigation.setParams({goBack: this.goBack, shouldShow: this.state.show });
}
onShow = () => {
if (this.state.steps >1) {
this.setState({show:true}, () => {this.props.navigation.setParam({shouldShow:true})} )
}
}
goBack= () =>{
this.setState({ steps: this.state.steps - 1 })
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
let headerLeft = null;
if (params.shouldShow) {
headerLeft = <TouchableOpacity onPress={() => params.goBack}>
<Image source={/* src */} style={Styles.navBarIcon} />
</TouchableOpacity>
}
return {
headerLeft: headerLeft,
headerTitle: 'Register',
headerStyle: Styles.navBar,
};
};
Since navigation options are static and not included inside your class, you cannot simply access states inside it. But you can follow below method.
// ------ inside your class -------
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
let headerLeft = null;
if(params.shouldShow) {
headerLeft = <TouchableOpacity onPress={() => params.onPressButton()}>
<Image source={/* source */} style={Styles.navBarIcon} />
</TouchableOpacity>
}
return {
headerLeft: headerLeft
};
};
componentDidMount(){
this.props.navigation.setParams({ onPressButton: this.onButtonPressedEvent, shouldShow:this.state.show });
}
onButtonPressedEvent = () =>{
// What you want to do when button pressed.
}
onShow = () =>{
if(this.state.count > 1){
this.setState({show:true}, () => {this.props.navigation.setParam({shouldShow:true})} )
}
}
Remember to call onShow method when you change the count to make changes in navigation.
Hello I 'm trying to bind a function in my Navigator Right Button,
But It gives error.
This is my code:
import React, { Component } from 'react';
import Icon from 'react-native-vector-icons/FontAwesome';
import Modal from 'react-native-modalbox';
import { StackNavigator } from 'react-navigation';
import {
Text,
View,
Alert,
StyleSheet,
TextInput,
Button,
TouchableHighlight
} from 'react-native';
import NewsTab from './tabs/news-tab';
import CustomTabBar from './tabs/custom-tab-bar';
export default class MainPage extends Component {
constructor(props) {
super(props);
}
alertMe(){
Alert.alert("sss");
}
static navigationOptions = {
title: 'Anasayfa',
headerRight:
(<TouchableHighlight onPress={this.alertMe.bind(this)} >
<Text>asd</Text>
</TouchableHighlight>)
};
render() {
return(
<View>
</View>
);
}
}
And Get error like this:
undefined is not an object (evaluating 'this.alertMe.bind')
When I use this method in render function it is working great but in NavigatonOption I cant get handled it. what can I do for this problem.
You should use this in you navigator function
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
title: '[ Admin ]',
headerTitleStyle :{color:'#fff'},
headerStyle: {backgroundColor:'#3c3c3c'},
headerRight: <Icon style={{ marginLeft:15,color:'#fff' }} name={'bars'} size={25} onPress={() => params.handleSave()} />
};
};
use the componentwillmount so that it can represent where you are calling function .
componentDidMount() {
this.props.navigation.setParams({ handleSave: this._saveDetails });
}
and then you can write your logic in the function
_saveDetails() {
**write you logic here for **
}
**no need to bind function if you are using this **
May be same as above ...
class LoginScreen extends React.Component {
static navigationOptions = {
header: ({ state }) => ({
right: <Button title={"Save"} onPress={state.params.showAlert} />
})
};
showAlert() {
Alert.alert('No Internet',
'Check internet connection',
[
{ text: 'OK', onPress: () => console.log('OK Pressed') },
],
{ cancelable: false }
)
}
componentDidMount() {
this.props.navigation.setParams({ showAlert: this.showAlert });
}
render() {
return (
<View />
);
}
}
react-navigation v5 version would be:
export const ClassDetail = ({ navigation }) => {
const handleOnTouchMoreButton = () => {
// ...
};
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<TouchableOpacity onPress={handleOnTouchMoreButton}>
<Icon name="more" />
</TouchableOpacity>
),
});
}, [navigation]);
return (
// ...
)
}
This is for navigation v4. You need to modify navigationoptions outside of the functional component. Your button event needs to pass a param via navigation.
pageName['navigationOptions'] = props => ({
headerRight: ()=>
<TouchableOpacity onPress={() => props.navigation.navigate("pageRoute",
{"openAddPopover": true}) } ><Text>+</Text></TouchableOpacity> })
and then in your functional component, you can use that param to do something like this:
useLayoutEffect(() => {
doSomethingWithYourNewParamter(navigation.getParam("openAddPopover"))
}, [navigation])
I have been struggling with something that sounds simple. I have been trying to get button when onpressed is called. Have tried several combinators but nothing works. Any ideas?
export default class JobScreen extends React.Component {
constructor(props) {
super(props);
}
static navigationOptions = ({navigation}) => ({
title: "Chat with"
});
onPressLearnMore(nav) {
// how do I update the title header
console.log("On Pressed" + nav)
}
render() {
const {navigate} = this.props.navigation;
return (
<View style={styles.container}>
<Button
onPress={() => {this.onPressLearnMore(navigate)}}
title="Learn More"
color="#841584"
/>
</View>
);
}
}
Since the navigationOptions has access to the navigation object, you can set some param on the current screen with this.props.navigation.setParam({ title: ‘some title’ }) and then access it in navigationOptions like this
static navigationOptions = ({ navigation }) => {
const { state: { params = {} } } = navigation;
return {
title: params.title || ‘default title’,
};
}
I've made a full-screen TextInput and would like to have an action performed when the Post button in the NavigationBar is pressed. However, because I have to make the method that the Button is calling in the onPress prop a static method, I don't have access to the state.
Here is my current code, and the state comes up undefined in the console.log.
import React, { Component } from 'react';
import { Button, ScrollView, TextInput, View } from 'react-native';
import styles from './styles';
export default class AddComment extends Component {
static navigationOptions = ({ navigation }) => {
return {
title: 'Add Comment',
headerRight: (
<Button
title='Post'
onPress={() => AddComment.postComment() }
/>
),
};
};
constructor(props) {
super(props);
this.state = {
post: 'Default Text',
}
}
static postComment() {
console.log('Here is the state: ', this.state);
}
render() {
return (
<View onLayout={(ev) => {
var fullHeight = ev.nativeEvent.layout.height - 80;
this.setState({ height: fullHeight, fullHeight: fullHeight });
}}>
<ScrollView keyboardDismissMode='interactive'>
<TextInput
multiline={true}
style={styles.input}
onChangeText={(text) => {
this.state.post = text;
}}
defaultValue={this.state.post}
autoFocus={true}
/>
</ScrollView>
</View>
);
}
}
Any ideas how to accomplish what I'm looking for?
I see you've found the solution. For future readers:
Nonameolsson posted how to achieve this on Github:
In componentDidMount set the method as a param.
componentDidMount () {
this.props.navigation.setParams({ postComment: this.postComment })
}
And use it in your navigationOptions:
static navigationOptions = ({ navigation }) => {
const { params } = navigation.state
return {
title: 'Add Comment',
headerRight: (
<Button
title='Post'
onPress={() => params.postComment()}
/>
),
};
};
Kinda like a hack but i use the global variable method where we assign this to a variable call foo. Works for me.
let foo;
class App extends Component {
static navigationOptions = ({ navigation }) => {
return {
title: 'Add Comment',
headerRight: (
<Button
title='Post'
onPress={() => foo.postComment() } <- Use foo instead of this
/>
),
};
};
componentWillMount() {
foo = this;
}
render() {
return (<div>Don't be a foo</div>)
}
}