Implementing a button on the header bar, react native - reactjs

I am trying to make a button on the right of the header bar so that it will change the order of the list, and i was thinking to have a state of the order and flip it as the button will be pressed and check wether that is true and false and show the list in the requested order.
But i get an error saying Notes.flipState is not a function. (In 'Notes.flipState()', 'Notes.flipState is undefined)
Any idea why is this hapening and how to solve it, below is my function flipState() and the navigationOptions.
state = {
desc: true
}
flipState() {
this.setState({ desc: !this.state.desc})
}
static navigationOptions = ({ flipState }) => {
return {
title: 'Upcoming Movies',
headerStyle: {
backgroundColor: 'blue',
},
headerTintColor: 'white',
headerTitleStyle: {
fontWeight: 'bold',
},
headerRight: () => (
<BorderlessButton
onPress={() => this.flipState()}
style={{ marginRight: 20 }}>
<Icon
name={'sort-alpha-asc'}
size={25}
color='gray'
/>
</BorderlessButton>
),
}
};

You can't call a "public" method inside of static method. "Play" with navigation state to pass data between header and content.
See setParams https://reactnavigation.org/docs/en/navigation-prop.html

A static method won't be able to access this .you have to pass function through the navigation params.
like
componentDidMount() {
this.props.navigation.setParams({
flipStat: this.flipStat,
});
}
get from navigationOption
static navigationOptions = ({ navigation }) => {
const flipStat = navigation.state.params.flipStat;
return </>
}

Related

Params not updating on state change ,react native

i have a react native app with 2 screens ,the first one is supposed to receive updates from a server and updates its state , upon clicking a submit button the app navigates to another screen that is dependent on the state of the first , i have managed to pass the values via the params and retrieve them in the second screen however i can not seem to get the updated values from the first screen as they are being replaced periodically ,how can i go about it, should i pass a reference of the object to the second screen and if so how would i go about it ..
The first screen , note the state in this screen is updating well and fine i console logged it after each setState , its the second screen that's not receiving the updates
handleSubmit = () => {
this.props.navigation.navigate("Tracking Bus", this.state.bus);
};
render() {
return (
<TouchableNativeFeedback onPress={this.handleSubmit}>
<View
style={{
width: 330,
height: 40,
backgroundColor: "#6FCF97",
alignSelf: "center",
justifyContent: "center",
}}
>
<Text style={{ alignSelf: "center", fontSize: 20 }}>Submit</Text>
</View>
</TouchableNativeFeedback>
</View>
</View>
);
}
The Second Screen , render function i.e
render() {
return (
setInterval(() => {
console.log(this.props.route.params.bus.location[1]);
}, 2000);
})
am expecting to get updated values but i i just get the initial values
Maybe this can work :
handleSubmit = () => {
this.props.navigation.navigate("Tracking Bus", {bus:this.state.bus});
};
and in your second screen:
render() {
return (
setInterval(() => {
const bus= this.props.navigation.getParam('bus');
console.log(bus);
}, 2000);
})
I may be late, but you can use componentWillReceiveProps().
export default class Example extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
// If needed
this.componentWillReceiveProps(this.props);
}
componentWillReceiveProps(props) {
if(typeof props.route === "object" && typeof props.route.params === "object" && props.route.params.bus !== undefined) {
this.props.navigation.push("Tracking Bus", {bus:props.route.params.bus});
}
}
// ...
}
You are passing the params incorrectly from first screen. You can try this and your fetching logic seems fine as this.props.route.params.bus
handleSubmit = () => {
this.props.navigation.navigate("Tracking Bus", { params: {bus : this.state.bus} });
};

TypeError: undefined is not an object (evaluating 'route.params')

I have a Drawer Navigator set up, with various screens.
On one screen, I have a FlatList with a simple TouchableOpacity like below:
<TouchableOpacity
onPress={() =>
navigation.navigate("ViewProject", {
screen: "viewProject",
params: { projectID: item.projectID },
})
}
>
</TouchableOpacity>
The navigation works, going to the viewProject screen, but no matter what I seem to try the route.params just doesn't seem to exist.
export default function viewProject({ route }) {
const projID = route.params?.projectID ?? 0; // ERRORS with TypeError: undefined is not an object (evaluating 'route.params')
console.log(projID);
}
I'm using the latest React Native, Navigation etc and TypeScript.
My only success is setting the initialRouteParams on the createStackNavigator that feeds into the drawer, and yet that's only accessible via navigation.state.params:
const screens = {
viewProject: {
screen: viewProject,
navigationOptions: ({ navigation }) => {
return {
headerTitle: () => (
<Header navigation={navigation} title={"View Project"} />
),
};
},
},
};
const viewProjectStack = createStackNavigator(screens, {
initialRouteParams: { projectID: 23 }, // This works, but it's static and I can't change it
});
Thanks in advance.
Stewart
You can pass like this:-
<Button
title="Go to Details"
onPress={() => {
/* 1. Navigate to the Details route with params */
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
/>
and receive like this:-
function DetailsScreen({ route, navigation }) {
/* 2. Get the param */
const { itemId } = route.params;
const { otherParam } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
);
}
source
Hope it helps!!!

react native how to re render refresh screen on tabBarOnPress

the screen do not get the new data until i close the app and open it again
i want to re-render the screen on tab press to refresh the screen and get the new data
Please see my below code
const DashboardTabNavigator = createBottomTabNavigator({
Home: { screen: Home,
navigationOptions: {
tabBarIcon: (
<Image style={{ width: 30, height: 30,tintColor:'white' }}
source={require('./assets/IconBootomTabNavigation/home_icon.png')} />
)
}
},
Category: { screen: Category,
navigationOptions: {
tabBarIcon: (
<Image style={{ width: 30, height: 30,tintColor:'white' }}
source={require('./assets/IconBootomTabNavigation/cat_icon.png')} />
)
}
}
I recommend you to place the code responsible for fetching the data inside componentDidMount lifecycle method. This way you can ensure you get the data after the initial render.
If the screens are not being re-rendered, please check this thread. You can use tabBarOnPress prop to call any component method.
You might also try this solution:
static navigationOptions = ({navigation}) => {
return {
tabBarOnPress: (tab, jumpToIndex) => {
if(!tab.focused) {
jumpToIndex(tab.index);
navigation.state.params.onFocus()
}
},
}
}
componentDidMount() {
this.props.navigation.setParams({
onFocus: your-data-fetching-method
})
}

How to Display Image in header using react-native-navigation?

I'm using react-native-navigation's startTabBasedApp component to build my tabs. In my Home tab I need to show one image/logo to the left of title. I have given my code below.
Navigation.startTabBasedApp({
tabs: [
{
label: "Home",
title: "Home",
screen: "awesome-Navigation.FindPlace",
icon: sources[0], //from my source obj
navigatorStyle: {
navBarBackgroundColor: '#535492',
navBarTextColor: 'white'
}
//is there any way to add image using navigationoptions inside this??
]
})
You can use tabIcon property
navigationOptions: () => ({
title: 'Contact Us',
headerStyle: { backgroundColor: '#191565' },
headerTintColor: '#FFF',
tabBarIcon:(<Icon name='navigate-before' size={40} color={'white'} />)
}
and in the tabBarOptions Below enable the
set showIcon:true
and set flexDirection of the tabStyle to row
tabStyle: {
flexDirection:'row'
}
You can use headerLeft inside your screen component. headerLeft has to be declared inside navigationOptions:
class ScreenComponent extends React.Component {
static navigationOptions = () => {
return {
headerLeft: <MaterialIcons .... /> // --> Your Icon
}
}
...
}

Conditional routing using React Navigation (React Native)

Building a React Native app, and I would to send a user to the next screen DEPENDING on the initial Select screen's state. So, if there there is 1 item selected, it should take the user to the Single screen. If more than 1, the Multiple screen.
As you can see, I made custom headerLeft and headerRight components. I would prefer to keep the routing this way, but somehow add the initial state into this context. Is there a way?
If I could somehow decouple the navigation options from the routes.js file and put them into the Screen components themselves, that would be awesome. But from what I researched, it doesn't seem like that the navigationOptions can directly access state.
Here's the relevant code (routes.js):
export default StackNavigator(
{
Select: {
screen: Select,
navigationOptions: ({ navigation }) => ({
headerLeft: <View />,
headerRight: (
<HeaderRight
navigation={navigation}
destination=""
showIcon
/>
)
})
},
Single: {
screen: Single,
navigationOptions: ({ navigation }) => ({
headerLeft: (
<HeaderLeft navigation={navigation} destination="back" showIcon />
),
headerRight: (
<HeaderRight navigation={navigation} destination="SingleSecond" />
)
})
},
Multiple: {
screen: Multiple,
navigationOptions: ({ navigation }) => ({
headerLeft: <HeaderLeft navigation={navigation} destination="back" />,
headerRight: (
<HeaderRight navigation={navigation} destination="MultipleSecond" />
)
})
},
},
{
headerMode: "float",
navigationOptions: ({ navigation }) => ({
title: `${navigation.state.routeName}`,
headerStyle: { backgroundColor: "#000" },
headerTitleStyle: {
color: "#fff",
textAlign: "center",
alignSelf: "center"
}
})
}
);
you can set params from a component these params can be accessed from navigation options.
this.props.navigation.setParams({ selectionState: "single" });
this.props.navigation.setParams({ selectionState: "multiple" });
and you can access the params from the navigation options like
static navigationOptions = ({navigation}) => {
let selected = navigation.state.params && navigation.state.params.selectionState;
return {
headerRight: ...
};
}
I hope this fills your needs, you need to set params after selecting something in your component. There is another way to dynamically set the initial state.
function getNavigation (selected = "single") {
return StackNavigator({
...,
{ initialState = selected === "single" ? "Single" : "Multiple" }
})
}
and then call this method with the selected argument to reset the screen.

Resources