React Native Navigation between functional components? - react-native

I am trying to navigate to the Main screen when Login button is pressed in Login.js. LoginForm loads perfectly but when I press the button I start receiving the error "TypeError: Undefined is not an object (evaluating 'navigation.navigate'). Before this was not a problem but it changed when I moved Login to a different component. I was getting a different error and I went through this but it didn't fix it: Getting undefined is not an object evaluating _this.props.navigation
Let me know if you need the whole code. Thanks :)
LoginForm.js
...
import Login from "./Login";
const LoginForm = props => {
return <Login />
}
...
Login.js
const Login = ({ navigation }) => {
return (
<TouchableOpacity
style={{ marginTop: 20 }}
activeOpacity={1}
onPress={() => navigation.navigate("Main")}
>
<View style={styles.loginButtonContainer}>
<Text style={styles.loginButtonText}>Login</Text>
</View>
</TouchableOpacity>
)}
...

I fixed it thanks to withNavigation. https://reactnavigation.org/docs/en/with-navigation.html
withNavigation is a higher order component which passes the navigation
prop into a wrapped component. It's useful when you cannot pass the
navigation prop into the component directly, or don't want to pass it
in case of a deeply nested child.
Login.js
import { withNavigation } from 'react-navigation'
const Login = ({ navigation }) => {
...
}
export default withNavigation(Login)
Anyway, if its possible, I would love to know how to fix it without this.

Related

react native textinput lost focus after 1 char type

I have this problem with ios but not with android. It only disturb the add task input the task edit and the list name edit. The input addList(It's the one with "What to do?" on the draw) in the header works fine.
UI drawing
Achitecture of components
I console log my component and I can see it rerender everytime I add a letter in the input field.
I checked on google and follow this:(can we link other website here?) https://www.codegrepper.com/code-examples/javascript/react+native+textinput+lost+focus+after+charter+type
Tried the the first solution with onBlurr and onFocus.
I tried to make a TextInput component for add task.
I even try with my component addList but it didn't solve the problem.
Anyone have faced this problem before? Is there anyway to by pass this?
My code without the import/style look like this:
const TaskList: FunctionComponent<TasksListProps> = ({
addTask,
deleteTask,
toggleTask,
editTaskName,
...props
}) => {
console.log('props', props);
const [nameOfTask, setNameOfTask] = useState('');
console.log('name', nameOfTask);
const textHandler = (enteredName: string) => {
setNameOfTask(enteredName);
};
const handleSubmitTask = () => {
if (nameOfTask === '') {
return;
}
addTask(props.listId, nameOfTask);
setNameOfTask('');
};
return (
<View style={styles.tasksListContainer}>
{props.tasks.map(task => (
<SingleTask
key={task.id}
task={task}
listId={props.listId}
deleteTask={deleteTask}
toggleTask={toggleTask}
editTaskName={editTaskName}
/>
))}
<View style={styles.taskInputContainer}>
<TextInput
style={styles.tasksTextInput}
value={nameOfTask}
onChangeText={textHandler}
placeholder="Write a task to do"
/>
<TouchableOpacity onPress={handleSubmitTask}>
<Image source={require('./Img/add-button.png')} />
</TouchableOpacity>
</View>
</View>
);
};
You can create a HOC and wrap your screen width DismissKeyboard
import { Keyboard } from 'react-native';
const DismissKeyboard = ({ children }) => (
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
{children}
</TouchableWithoutFeedback>
);
That because Re render.
Try to make the input with the main component of the page to test it.
Then check where the error with re-render

navigation does not work when imported - React native

When I use props.navigation.navigate("example"), it works normally. But if I import the component on another page it doesn't work anymore, props returns an empty object.
Works Fine:
const Menu = props =>{
console.log(props)
return(
<View style={styles.menuStyle}>
<TouchableOpacity style={styles.topicDiv} onPress={() =>props.navigation.navigate("Ads")}>
<View>
<Image style={styles.topicStyle} source={require ("../assets/security-camera.png")}/>
<Text style={styles.textStyle}>Câmeras</Text>
<Text style={styles.subTextStyle}>Veja como está a praia ao vivo 📷</Text>
If i try import Menu, navigation does not work:
import React from "react";
import { View } from "react-native";
import Menu from "./menu";
const Supermenu = () =>{
return(
<View>
<Menu></Menu>
</View>
)
}
export default Supermenu
If you use <Menu> inside of another component like <Supermenu>, React Navigation has no way to pass its navigation property in there. It only happens automatically if a component is a direct child of a screen (or its component property).
To have navigation available in Menu regardless of its position in the hierarchy, as long as it's a child of <NavigationContainer>, the best way is to make use of the useNavigation hook:
import { useNavigation } from '#react-navigation/core';
const Menu = props =>{
const navigation = useNavigation();
return (
<View style={styles.menuStyle}>
<TouchableOpacity style={styles.topicDiv} onPress={() => navigation.navigate("Ads")}>
...
See documentation for more detail.
If you are on an older version, there was also a HOC withNavigation that you could use.
You could also do the same in Supermenu and then pass navigation down manually.
use import {userNavigation} from '#react-navigation/core' instead of props navigate or you can add navigation props to the Menu component.

Null is not an object while creating navigation between screens in expo project

I need to open new screen after clicking on the button. For it I made the following steps:
1) Installed this library
2) Created a new screen and added it to the folder with other screens (DetailInfoScreen is a new screen, which should be opened and HomeScreen is a screen, where a button, after clicking on which new screen should be opened):
3) Added the following lines of code:
import { Navigation } from 'react-native-navigation';
import DetailInfoScreen from './DetailInfoScreen';
class HomeScreen extends Component {
constructor(props) {
super(props);
this.onPressSearch = this.onPressSearch.bind(this);
Navigation.registerComponent('DetailInfoScreen', () => DetailInfoScreen);
}
goToScreen = (screenName) => {
Navigation.push(this.props.componentId, {
component: {
name: screenName
}
});
}
render() {
const { list, text } = this.props;
return (
<View style={styles.container}>
<View style={styles.searchContainer}>
<TouchableOpacity
onPress={this.goToScreen('DetailInfoScreen')}
>
<View>
<Text>Search</Text>
</View>
</TouchableOpacity>
</View>
);
}
But when I run the project I have the following error:
And one more moment which disturbs me is that autocorrection in vscode doesn't see my new screen while importing:
Maybe it doesn't play any role, but still. So, what's the reason of the problem and how can I solve it?
You can simply navigate to another screen by using this:
<TouchableOpacity
onPress={() => this.props.navigation.navigate('DetailInfoScreen')>
<Text>Search</Text>
</TouchableOpacity>
I would personally advice for you to use react-navigation instead of react-native-navigation, you can read more on this link

Programatically hiding and showing individual tabs in React Native Router Flux Tabbar

I have a tabbar in my app using React Native Router Flux. There are a couple use cases where hiding or showing specific tabs based on the current user would be very helpful. The main ones I have run into are:
AB testing new tabs to specific users
Showing a special admin tab to certain users with certain privileges
The react-native-router-flux library does not support any options to do this from what I can see. How can I achieve this functionality?
The default tabbar component in react-native-router-flux is just the component from the react-navigation-tabs library. You can import this component directly into your code, customize as needed, and then pass it to react-native-router-flux through the tabBarComponent prop (documented here).
I created a new component, which you should be able to copy directly and just change the logic for actually hiding the tabs based on your state:
import React from 'react'
import { BottomTabBar } from 'react-navigation-tabs'
import { View, TouchableWithoutFeedback } from 'react-native'
import { connect } from 'react-redux'
const HiddenView = () => <View style={{ display: 'none' }} />
const TouchableWithoutFeedbackWrapper = ({
onPress,
onLongPress,
testID,
accessibilityLabel,
...props
}) => (
<TouchableWithoutFeedback
onPress={onPress}
onLongPress={onLongPress}
testID={testID}
hitSlop={{
left: 15,
right: 15,
top: 5,
bottom: 5,
}}
accessibilityLabel={accessibilityLabel}
>
<View {...props} />
</TouchableWithoutFeedback>
)
const TabBarComponent = props => (
<BottomTabBar
{...props}
getButtonComponent={({ route }) => {
if (
(route.key === 'newTab' && !props.showNewTab) ||
(route.key === 'oldTab' && props.hideOldTab)
) {
return HiddenView
}
return TouchableWithoutFeedbackWrapper
}}
/>
)
export default connect(
state => ({ /* state that you need */ }),
{},
)(TabBarComponent)
And then simply imported and used that in my Tabs component:
<Tabs
key="main"
tabBarComponent={TabBarComponent} // the component defined above
...
Detailed look at where these things are getting passed to
Looking at the line of the source of react-native-router-flux, it is using createBottomTabNavigator from the react-navigation library, and passing no component if you do not pass a custom tabBarComponent. The createBottomTabNavigator method in react-navigation comes from this line of the library, and is actually defined in react-navigation-tabs. Now, we can here see in react-navigation-tabs that if no tabBarComponent has been passed, it simply uses BottomTabBar, also defined in react-navigation-tabs. This BottomTabBar, in turn, takes a custom tab button renderer through props, called getButtonComponent.

React Native - Push one Screen To Another have issue

I used the 'StackNavigator', I have issue to push when navigation code write in button event. but its working fine if we directly code onPress event,
Import file.
import { StackNavigator } from "react-navigation";
import SignUpScreen from "./SignUp";
Push another is working :
render() {
console.disableYellowBox = true;
const { navigate } = this.props.navigation;
return (
<View style={styles.viewStyle}>
<TouchableHighlight style = {styles.buttonStart}
onPress={() => navigate("SignUpCompany")}>
<Image
source={require('./Images/hire.png')}
/>
</TouchableHighlight>
</View>
);
}
Push another via function is not working :
pushcode() {
console.log('call');
this.props.navigation.navigate('SignUp');
}
render() {
return (
<TouchableHighlight style = {styles.buttonStart}
onPress={this.pushcode}>
<Image
source={require('./Images/hire.png')}
/>
</TouchableHighlight>
);}
ERROR ON CLICK BUTTON :
Thanks. Please help me.
Look like you are using the push extra in this line
this.props.navigation.navigate.push('SignUp');
Try this will work for you
this.props.navigation.navigate('SignUp');
May be this can help you
I think you miss the function bind within constructor --- that's why you got undefined is not an object (evaluating 'this.props.navigation'). because this is undefined inside pushcode function scope.
add below into your constructor:
constructor(props) {
super(props);
this.pushcode = this.pushcode.bind(this);
...
}