React Navigation Back Button Doesnt do anything - react-native

Basically what the title says. I am trying to create a back button by passing the current page routeName into the navigation state and then on the detail page I retrieve the params and pass the routeName into the goBack button. But when I click the button it doesnt do anything. I checked to see if the routeName of the previous page was in the state but it still doesnt do anything.
List Screen
Here is my Button, I am passing an id from a reducer and the routeName of the currentscreen into the navigation params
renderList = () => {
const { lists } = this.props;
if(lists) {
return (lists.data.map(el => {
return (
<TouchableOpacity
key={el.id}
onPress={ () => this.props.navigation.navigate('PostItem', { nid: el.id, prevScreen: this.props.navigation.state.routeName})}>
<Text>Next Screen</Text>
</TouchableOpacity>
)}
))
}
}
ListDetail Screen
class listDetail extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
this.props.loadPost('article', this.props.navigation.state.params.nid + '?include=field_image')
}
render() {
const { goBack } = this.props.navigation;
return (
<View>
<Button title="Back" onPress={() => goBack(this.props.navigation.state.params.prevScreen)} />
{ this.renderPost() }
</View>
)
}
}
any suggestions?

The parameter in goBack refers to the key not the routeName.
From the reactnavigation goBack docs
Note -- a key is not the name of the route but the unique identifier you provided when navigating to the route. See navigation key.
So in your example I'd try to call navigate with a key parameter
For renderList onPress could be
onPress={ () => this.props.navigation.navigate({ routeName: 'PostItem', key: `PostItem_${el.id}`, params: { nid: el.id } })}>
Then in ListDetail
<Button title="Back" onPress={() => goBack(`PostItem_${this.props.navigation.state.params.nid}`)} />

Related

React Native - Rerunning the render method

I have a file here that defines an icon for the title.
static navigationOptions = ({ navigation }) => {
return {
headerRight: () => (<HomeHeaderIcon/>)
}
};
HomeHeaderIcon.js
export default class HomeHeaderIcon extends Component {
async componentDidMount(){
const token = await AsyncStorage.getItem('token');
this.setState({token});
}
state={
token:null
};
render() {
return (
<View>
{
this.state.token ===null
?
(
<TouchableOpacity
onPress={() => (NavigationService.navigate("LogStack"))}>
<Icon name="ios-power" size={30} style={{color: "white",marginRight:wp("5%")}}/>
</TouchableOpacity>
)
:
(
<TouchableOpacity
onPress={() => (NavigationService.navigate("Profile"))}>
<Icon name="ios-home" size={30} style={{color: "white",marginRight:wp("5%")}}/>
</TouchableOpacity>)
}
</View>
);
}
}
The system works exactly as I want. If there is a token, I say icon1 or icon2 show. The problem is I do this in componentDidMount, the icon does not change without refreshing the page. How do I render it again?
componentDidMount is called, as the name suggests, just once, when the component is mounted. Use componentDidUpdate to decide how your component behaves based on what piece of props or state has changed.
Read the documentation for more information regarding lifecycle methods.

How to skip back/modify navigation

I have a stackNavigation which works great. 3 screens : DeviceList / DeviceDetail / DevideAdd. The normal paths is (1) DeviceList > DeviceDetail or (2) DeviceList > DeviceAdd > DeviceDetail.
But when user use the path (2), I want that the back button of the DeviceDetail screen go to DeviceList. Or for the moment, it's going to DevideAdd.
Here is my navigation:
const DeviceStackNavigator = createStackNavigator({
DeviceList: {
screen: DeviceList,
},
DeviceDetail: {
screen: DeviceDetail,
},
DeviceAdd: {
screen: DeviceAdd,
},
});
How to achieve it ?
The key attribute 'goBack()' is a dynamically generated string that is created each time you navigate to a new 'react-navigation' path.
So if you want to go from DeviceDetail to DeviceList, what you have to do is to pass the key of DeviceAdd down to DeviceDetail, and then call goBack() with the key.
DeviceAdd.js
render() {
const { state, navigate } = this.props.navigation;
return (
<View>
<Button title="Go to DeviceDetail" onPress={ () => {
navigate('DeviceDetail', { go_back_key: state.key });
}} />
</View>
);
}
DeviceDetail.js
render() {
const { state, goBack } = this.props.navigation;
const params = state.params || {};
return (
<View>
<Button title="Back to DeviceList" onPress={ () => {
goBack(params.go_back_key);
}} />
</View>
);
}

React Navigation - Setting params without navigating to the scene

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);

React Native Navigation - Action using Component's State

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>)
}
}

How to access to a function in a specific js file from navigation Bar in React Native?

I'm trying to access to a function in a specific js(chat.js in my local) file from the nagivation Bar in React Native.
Naviagation Bar is stated in index.ios.js and the code is given below.
render() {
....
<Navigator
initialRoute={{ title: 'Log In Page', index: 0, component: FirstPage }}
configureScene={() => {
return Navigator.SceneConfigs.FloatFromRight;
}}
navigationBar={
<Navigator.NavigationBar
routeMapper={{
LeftButton: (route, navigator, index, navState) =>
{
if (route.index === 0) {
return null;
} else {
return (
<TouchableHighlight onPress={() => navigator.pop()}>
<Text style={styles.route_title}> Back </Text>
</TouchableHighlight>
);
}
},
RightButton: (route, navigator, index, navState) =>
{
if (route.index === 10000){
return (<Text>Done</Text>);
}else{
return null;
}
},
Title: (route, navigator, index, navState) =>
{ return (<Text style={styles.route_title}> {route.title} </Text>); },
}}
style={{backgroundColor: '#28b496'}} />
}
...
When I click 'back' in the page(chat.js), I want to execute a specific function that is stated in chat.js file, such as pusher.unsubscribe('test_channel');.
How would I be able to access an internal function from the top in React-native?
I'm looking forward to seeing any opinion on this matter!
Best
export this function
then import it in your index file
In order to achieve that you can use 'navigator' parameter. You can access component's functions through this parameter. You can access it by using structure below
First write a method in Navigator component
<Navigator initialRoute = {{name:'home'}}
renderScene = {this.renderScene.bind(this)}
navigationBar = {<Navigator.NavigationBar routeMapper={NavigationBarRouteMapper} style={styles.navBar}/>}
callerFunction= {() => this.yourFunctionName()} // this is what you should add
/>
then assign this method the function you want to call
then you can access yourFunction through this callBack function(callerFunction).
{navigator.props.callerFunction()}
Definetely you can send parameters as well.