Navigation with React Native Base - javascript

I want to navigate to another screen (i.e 'Details') when I hit the login button. This is my working main code: (could be checked on Snack Expo)
import React, { Component } from 'react';
import { Container, Header, Left, Body, Right, Button, Title, Text, Form, Item, Input, Label} from 'native-base';
import { StackNavigator } from 'react-navigation';
import { DrawerNavigator } from "react-navigation";
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: '',
};
}
render() {
return (
<Container>
<Text >Instaride</Text>
<Form>
<Item floatingLabel>
<Label onChangeText={(text) => this.setState({username: text})}>Username</Label>
<Input
value={this.state.username}
onChangeText={username => this.setState({ username })}
placeholder={'Username'}
/>
</Item>
<Item floatingLabel last>
<Label >Password</Label>
<Input
value={this.state.password}
onChangeText={password => this.setState({ password })}
placeholder={'Password'}
secureTextEntry={true}
/>
</Item>
</Form>
<Left>
<Button >
<Text>Login</Text>
</Button>
<Text >Forgot Password?</Text>
</Left>
<Right>
<Button hasText transparent>
<Text>Sign Up Here</Text>
</Button>
</Right>
</Container>
);
}
}
class DetailsScreen extends React.Component {
render() {
return (
<Text>Details Screen</Text>
);
}
}
class RegisterationScreen extends React.Component {
render() {
return (
<Text>sign up time</Text>
);
}
}
However, I get an error when I add this:
const HomeScreenRouter = DrawerNavigator(
{
Home: { screen: Login },
Chat: { screen: DetailsScreen },
Profile: { screen: RegisterationScreen }
}
)
I can not really figure out a way to combine all of these:
onPress={() => this.props.navigation.navigate("Details")}
Also, what exactly should I be exporting at the end of the code?

You should do something like this to work...
import React, { Component } from 'react';
import { Container, Header, Left, Body, Right, Button, Title, Text, Form, Item, Input, Label} from 'native-base';
import { StackNavigator } from 'react-navigation';
import { DrawerNavigator } from "react-navigation";
import { createAppContainer } from 'react-navigation';
class Login extends Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: '',
};
}
render() {
return (
<Container>
<Text >Instaride</Text>
<Form>
<Item floatingLabel>
<Label onChangeText={(text) => this.setState({username: text})}>Username</Label>
<Input
value={this.state.username}
onChangeText={username => this.setState({ username })}
placeholder={'Username'}
/>
</Item>
<Item floatingLabel last>
<Label >Password</Label>
<Input
value={this.state.password}
onChangeText={password => this.setState({ password })}
placeholder={'Password'}
secureTextEntry={true}
/>
</Item>
</Form>
<Left>
<Button >
<Text>Login</Text>
</Button>
<Text >Forgot Password?</Text>
</Left>
<Right>
<Button hasText transparent>
<Text>Sign Up Here</Text>
</Button>
</Right>
</Container>
);
}
}
class DetailsScreen extends React.Component {
render() {
return (
<Text>Details Screen</Text>
);
}
}
class RegisterationScreen extends React.Component {
render() {
return (
<Text>sign up time</Text>
);
}
}
const HomeScreenRouter = createStackNavigator(
{
Details: { screen: Details },
}
)
export default createAppContainer(HomeScreenRouter);

Related

Not able to call onChange function of a TextInput in Redux, React JS

I am working on an app with React and Redux and displaying some data from API in TextInput control. But now I am not able to edit the data in the TextInput. Following is my complete code of the class:
import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import Article from "grommet/components/Article";
import Box from "grommet/components/Box";
import Button from "grommet/components/Button";
import Header from "grommet/components/Header";
import Heading from "grommet/components/Heading";
import Section from "grommet/components/Section";
import AdminMenu from "../../components/Nav/Admin";
import NavControl from "../../components/Nav/Control";
import { getMessage } from "grommet/utils/Intl";
import Notices from "../../components/Notices";
import CheckBox from "grommet/components/CheckBox";
import TextInput from "grommet/components/TextInput";
import { pageLoaded } from "../utils";
import {
recognitionSettingsLoaded,
recognitionSettingsSaved,
} from "../../actions/settings-recognition";
import dashboard from "../../reducers/dashboard";
class Settings extends Component {
constructor(props) {
super(props);
this.handleDaysChange = this.handleDaysChange.bind(this);
this.handleActiveChange = this.handleActiveChange.bind(this);
}
componentDidMount() {
const { dispatch, settingRecognition } = this.props;
console.log(this.props.state);
console.log(dashboard);
dispatch(recognitionSettingsLoaded("2"));
pageLoaded("Configuration");
}
onSave() {
const { survey, dispatch } = this.props;
dispatch(
recognitionSettingsSaved(
this.props.settingRecognition.days,
this.props.settingRecognition.active
)
);
}
handleDaysChange(e) {
const days = e.target.value;
settingRecognition.days = days;
}
handleActiveChange(e) {
const active = e.target.value;
settingRecognition.active = active;
}
render() {
const { dispatch, settingRecognition } = this.props;
console.log("render method");
console.log(settingRecognition);
const { intl } = this.context;
return (
<Article primary={true}>
<Header
direction="row"
justify="between"
size="large"
pad={{ horizontal: "medium", between: "small" }}
>
<NavControl name={getMessage(intl, "Configuration")} />
<AdminMenu />
</Header>
<Box pad={{ horizontal: "medium", vertical: "medium" }}>
<Heading tag="h4" margin="none">
{getMessage(intl, "RecognitionLifetime")}
</Heading>
<Heading tag="h5" margin="none">
{getMessage(intl, "DefineIsRecognitionTemporary")}
</Heading>
<Box direction="row">
<CheckBox
toggle={true}
checked={settingRecognition.active}
onChange={this.handleActiveChange}
/>{" "}
<Heading tag="h3" margin="none">
{getMessage(intl, "NewUserActive")}
</Heading>
</Box>
<Heading tag="h3" margin="none">
{getMessage(intl, "HideAfter")}
</Heading>
<Box direction="row">
<TextInput
placeholder="type here"
value={settingRecognition.days.toString()}
onChange={this.handleDaysChange}
/>{" "}
<Heading tag="h3" margin="none">
{getMessage(intl, "Days")}
</Heading>
</Box>
<Button
path="/recognition-settings"
label={getMessage(intl, "NewUserSave")}
primary={true}
onClick={() => {
this.onSave();
}}
/>
</Box>
<Notices />
</Article>
);
}
}
Settings.propTypes = {
dispatch: PropTypes.func.isRequired,
settingRecognition: PropTypes.object.isRequired,
};
Settings.contextTypes = {
intl: PropTypes.object,
};
const mapStateToProps = (state) => ({
settingRecognition: state.settingRecognition,
});
export default connect(mapStateToProps)(Settings);
I have created handleDaysChange function which should run on the text change of TextInput control. I have done similar thing for the checkbox and that works fine but I am not able to get it working for the TextInput.
You are not binding your change events.
Try this....
class Settings extends Component {
constructor(props){
super(props);
this.handleDaysChange = this.handleDaysChange.bind(this);
this.handleActiveChange = this.handleActiveChange.bind(this);
}
componentDidMount(){
....
}
......
}
and change this
<CheckBox
toggle={true}
checked={settingRecognition.active}
onChange={(e) => this.handleActiveChange(e)}
/>
To this
<CheckBox
toggle={true}
checked={settingRecognition.active}
onChange={this.handleActiveChange}
/>
same for text input
<TextInput
placeholder="type here"
value={settingRecognition.days.toString()}
onChange={this.handleDaysChange}
/>
You need to set up two-way-binding so that the content of the textInput reflects the prop that you set in your onChange function. Try giving your textInput a property of value={this.settingRecognition.days}

How to use pagination in Reactjs application

I am implementing pagination for my blog page by using react-js-pagination.
I am unable to fix this pagination ui and its content per page
Bind my data accordingly per page
I have tried to import less from bootstrap but it is not rendering for this.
Any suggestion on this to solve this pagination issue?
Updated code: it is working now
//blog.js
import React, {Component} from 'react';
import {Card, Grid, Cell, Dialog, CardMenu, Button, CardTitle,
CardText, CardActions, FABButton, Icon} from'react-mdl';
import { Container} from 'reactstrap';
import { connect } from 'react-redux';
import { getBlog, deleteBlog } from '../../actions/resumeActions';
import PropTypes from 'prop-types';
import Loading from './Loading';
import Moment from 'moment';
import BlogModal from "./BlogModal";
import Pagination from "react-js-pagination";
class Blogs extends Component{
constructor(props) {
super(props);
this.state = {
modal: false,
justClicked: null,
activePage: 1
};
this.handleOpenDialog = this.handleOpenDialog.bind(this);
this.handleCloseDialog = this.handleCloseDialog.bind(this);
}
static propTypes = {
getContact: PropTypes.func.isRequired,
deleteContact: PropTypes.func.isRequired,
resume: PropTypes.object.isRequired,
isAuthenticated: PropTypes.bool,
auth: PropTypes.object.isRequired,
loading: PropTypes.object.isRequired
}
toggle = () => {
this.setState({
modal: !this.state.modal
});
}
handleOpenDialog(id) {
this.setState({
openDialog: true,
justClicked: id
});
}
handleCloseDialog() {
this.setState({
openDialog: false
});
}
componentDidMount() {
this.props.getBlog();
}
onDeleteBlogClick = (id) => {
this.props.deleteBlog(id);
};
handlePageChange(pageNumber) {
console.log(`active page is ${pageNumber}`);
this.setState({activePage: pageNumber});
}
cardDialog(blogs, user){
return(
<Grid style={{padding: 0, display: 'contents'}}>
{blogs.map(({ _id, blog_name, blog_desc, blog_image_link, blog_by }) => (
<Cell col={12}>
<Dialog open={this.state.openDialog && this.state.justClicked === _id} className="open-dialog">
<CardTitle style={{color: '#fff', height: '176px', backgroundImage: `url(${blog_image_link})`, backgroundPosition: 'center',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat'}}>{blog_name}</CardTitle>
<CardText>
{blog_desc}
</CardText>
<CardActions border>
<p style={{float:'right', fontWeight:'bold'}}>Author: {blog_by}</p>
</CardActions>
<CardMenu style={{color: '#fff'}}>
<FABButton onClick={this.handleCloseDialog} className="close-button" >
<Icon name="close" />
</FABButton>
</CardMenu>
</Dialog>
</Cell>
))}
</Grid>
)
}
render(){
const { blogs, loading} = this.props.resume;
const { isAuthenticated, user } = this.props.auth;
const itemsPerPage = 1;
let activeBlogs = blogs.slice (itemsPerPage * this.state.activePage - itemsPerPage, itemsPerPage * this.state.activePage)
return(
<Container>
{loading ? (
<div><Loading/></div>
) : (
<div>
{/* blog modal */}
<BlogModal />
{/* card dialog */}
{this.cardDialog(blogs, user)}
<Grid style={{padding: 0}} id="todo">
{activeBlogs.map(({ _id, blog_name, blog_by, date }) => (
<Cell key={_id} data-id={_id}>
{ this.props.isAuthenticated && (user.is_admin === true) ?
<Button className="remove-btn"
color="danger"
size="sm"
onClick= {this.onDeleteBlogClick.bind(this, _id)}>
×
</Button> : null }
<Card shadow={5} className="cards-grid">
<CardTitle className="card-title-image"></CardTitle>
<CardText>
<b>{blog_name}</b>
</CardText>
<CardActions border>
<Button className="blog-read-me-button" onClick={this.handleOpenDialog.bind(this, _id)}>Read </Button>
<p style={{ fontStyle:'italic', fontWeight:'bold'}}>By-{blog_by} <span style={{float:'right',}}>{Moment(date).format('Do MMMM YYYY')}</span></p>
</CardActions>
</Card>
</Cell>
))}
</Grid>
</div>
)}
<Pagination
activePage={this.state.activePage}
itemsCountPerPage={1}
totalItemsCount={2}
pageRangeDisplayed={1}
onChange={this.handlePageChange.bind(this)}
itemClass='page-item'
linkClass='page-link'
/>
</Container>
)
}
}
const mapStateToProps = (state) => ({
resume: state.resume,
isAuthenticated : state.auth.isAuthenticated,
auth: state.auth,
loading: state.apiCallsInProgress > 0
});
export default connect(mapStateToProps, {getBlog, deleteBlog }) (Blogs);
//current ui
This is the default style of react-js-pagination. You have to style it yourself. However as far as I see, you are using bootstrap in your application, so you could use their styles in the following way:
<Pagination
activePage={this.state.activePage}
itemsCountPerPage={1}
totalItemsCount={2}
pageRangeDisplayed={1}
onChange={this.handlePageChange.bind(this)}
itemClass='page-item'
linkClass='page-link'
/>

Position component in React Native with inline styling

I'm trying to move the pizza icon to be directly right of the search bar.
Not only have I not been able to move the search pizza icon to the right of the search bar, I have not been able to move it at all.
This main pizza icon is in MainPage as :
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import axios from 'axios';
import Card from './Card'
import NewCard from './NewCard'
export default class MainPage extends Component {
constructor(props) {
super(props)
this.createLibrary = this.createLibrary.bind(this)
this.state = {
librarys: []
}
}
componentDidMount() {
axios.get('http://localhost:3000/libraries')
.then(res => {
const librarys = res.data;
this.setState({ librarys: librarys });
console.log(this.state.librarys)
})
}
//Create card
createLibrary(library) {
axios.post('http://localhost:3000/libraries', { library })
.then(res => {
this.updateLibrary(library)
})
}
updateLibrary(library){
let newLibrarys = this.state.librarys.filter((f) => f.id !== library.id)
newLibrarys.unshift(library)
this.setState({
librarys: newLibrarys
})
}
render() {
return (
<View>
<NewCard
createLibrary={this.createLibrary}
style={{position: 'absolute',
left: 20,
top: 20}}
/>
<Card style={{justifyContent: 'flex-end'}} librarys={this.state.librarys}/>
</View>
);
}
}
This is the new card component:
import React, { Component } from 'react';
import { Text, View, TextInput, Dimensions } from 'react-native';
import { Header, Form, Item, Input, Icon, Button } from "native-base";
export default class MainPage extends Component {
constructor(props) {
super(props)
this.state = {
title: '',
desc: '',
markdown: '',
showHide: 'none'
}
}
submitForm = () => {
let title = this.state.title
let desc = this.state.desc
let markdown = this.state.markdown
let library = {title: title, desc: desc, markdown: markdown}
this.props.createLibrary(library)
}
showForm = () => {
this.state.showHide === 'none' ?
this.setState({showHide: 'flex'}) :
this.setState({showHide: 'none'})
}
render() {
const formStyle = {
display: this.state.showHide,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height
}
return (
<View>
<Icon
name='pizza'
onPress={this.showForm}
style={{display: this.state.showHide === 'none' ? 'flex' : 'none'}}
/>
<Form style={formStyle} >
<Item>
<Input
placeholder="Title"
name="title"
onChangeText={(value) => this.setState({title: value})}
/>
</Item>
<Item>
<Input
placeholder="Description"
name="desc"
onChangeText={(value) => this.setState({desc: value})}
/>
</Item>
<Item>
<Input
placeholder="Markdown"
name="markdown"
onChangeText={(value) => this.setState({markdown: value})}
/>
</Item>
<Button
light
onPress={this.submitForm.bind(this)}
>
<Text> Submit </Text>
</Button>
</Form>
</View>
);
}
}
The search bar is in the card component:
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { Header, Form, Item, Input, Icon, Button, Accordion } from "native-base";
export default class MainPage extends Component {
constructor(props) {
super(props)
this.state = {
activeIndex: null,
search: '',
sortCards: "newest",
search: ''
}
}
render() {
var filteredCards = this.props.librarys.filter(
(library) => {
return library.title.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1 || library.desc.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1
})
const dataArray = filteredCards.map(
(library) => {
return {title: library.title, content: library.desc}
}
)
return (
<View>
<Header searchBar rounded>
<Item>
<Icon name="ios-search" />
<Input placeholder="Search"
onChangeText={(value) => this.setState({search: value})}
/>
<Icon name="ios-people" />
</Item>
<Button transparent>
<Text>Search</Text>
</Button>
</Header>
<Accordion dataArray={dataArray} expanded={0}/>
</View>
);
}
}
I've tried different permutations of inline styling, but none of them seem to work. I'm very familiar with React, but I'm new to React Native.
Edit:
This is my current styling:
return (
<View>
<NewCard
createLibrary={this.createLibrary}
style={{
position: 'relative',
left: 20,
top: 20,
zIndex: 1
}}
/>
<Card style={{justifyContent: 'flex-end', position: 'absolute', zIndex: 0}} librarys={this.state.librarys}/>
</View>
);
}
}
Using a nested view with a "row" direction is useful here.
<view style={{flex:1}}>
<view style={{flexDirection:"row"}} >
<Searchabr/>
<Icon/>
...
</view>
</view>
If you want to position over the other item, you have to make the position: relative for the parent and set position: absolute for your icon. once you do this, you will now be able to place it using top, left, right, bottom and z-index properties accordingly.

Navigate Issue From a ListView

I have 2 listview in my homepage (TodoDetail.js and TodoDetailChecked.js) and there is TouchableOpacity's in this listview's rows.. When I click this TouchableOpacity, I want to go to Profile.js page.
But the problem is when I click, it can not find props.navigation.navigate.
I tried to catch logs in componentDidMount but nothing about navigate.
componentDidMount() {
console.log(this.props);
}
Please help me...
Here is the code;
TodoDetail.js
import React, { Component } from 'react';
import { Card, Icon } from 'react-native-elements';
// import Checkbox from '../components/Checkbox';
import { Text, View, TouchableOpacity } from 'react-native';
import * as firebase from 'firebase';
import {
Menu,
MenuOptions,
MenuOption,
MenuTrigger,
} from 'react-native-popup-menu';
class TodoDetail extends Component {
componentDidMount() {
console.log(this.props.navigation.navigate('TodoDetail'));
}
clickText() {
const { todo } = this.props.todos;
// const { navigate } = this.props.navigation;
return (
<TouchableOpacity onPress={this.seeDetail.bind(this)} >
<Text numberOfLines={1}> {todo} </Text>
</TouchableOpacity>
);
}
seeDetail() {
const { navigate } = this.props.navigation;
navigate("Profile", { name: "Jane" });
console.log('click');
}
render() {
//Serverdan çekilenler
const uid = this.props.todos.uid;
const success = this.props.todos.success;
//Tarih olayları
const date = new Date();
const day = date.getDate();
const tomorrow = day + 1;
const year = date.getFullYear();
const month = date.getMonth();
//Style tanımlama
const { container, iconContainer, subContainer } = styles;
if (success === 0) {
return (
<Card>
<View style={container}>
<View style={iconContainer}>
<TouchableOpacity onPress={() => firebase.database().ref(`todos/personal/${uid}/success`).set(1)} >
<Icon name='check-box-outline-blank' />
</TouchableOpacity>
<View style={subContainer}>
{this.clickText()}
</View>
<View style={iconContainer}>
<Menu>
<MenuTrigger>
<Icon name='keyboard-arrow-down' />
</MenuTrigger>
<MenuOptions>
<MenuOption onSelect={() => firebase.database().ref(`todos/personal/${uid}/date`).set({ day, year, month })} >
<Text style={{ color: 'black' }} > Son Tarihi Bugün </Text>
</MenuOption>
<MenuOption onSelect={() => firebase.database().ref(`todos/personal/${uid}/date`).set({ day: tomorrow, year, month })} >
<Text style={{ color: 'black' }} > Son Tarihi Yarın </Text>
</MenuOption>
<MenuOption onSelect={() => firebase.database().ref(`todos/personal/${uid}/date`).remove()} >
<Text style={{ color: 'black' }} > Son Tarihi Kaldır </Text>
</MenuOption>
<MenuOption onSelect={() => firebase.database().ref(`todos/personal/${uid}`).remove()} >
<Text style={{ color: 'red' }} > Yapılacak İşi Sil </Text>
</MenuOption>
</MenuOptions>
</Menu>
</View>
</View>
</View>
</Card>
);
} else
if (success === 1) {
return (
null
);
}
}
}
Todolist.js
createDataSource({ studentsArray }) {
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
this.dataSource = ds.cloneWithRows(studentsArray.reverse());
}
changeScreen() {
this.setState({ screenSize: false });
}
changeScreenBack() {
this.setState({ screenSize: true });
}
renderRow(todos) {
return <TodoDetail todos={todos} />;
}
renderRow2(todos) {
return <TodoDetailChecked todos={todos} />;
}
render() {
// const { navigate } = this.props.navigation;
const { container, inputContainer, inputText } = styles;
if (!this.state.screenSize) {
return (
<View style={container} >
<View style={inputContainer} >
<Icon name={'add'} />
<TextInput
style={inputText}
underlineColorAndroid='transparent'
placeholder="Yapılacak iş ekle..."
placeholderTextColor="#FFFFFF"
value={this.props.todo}
onChangeText={todo => this.props.todoChanged(todo)}
/>
<Button
onPress={this.addToDo.bind(this)}
title="Ekle"
color="#841584"
accessibilityLabel="Learn more about this purple button"
/>
</View>
<View style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<ListView
enableEmptySections
dataSource={this.dataSource}
renderRow={this.renderRow}
/>
</View>
<View style={{ flex: 1 }}>
<View style={{ height: 1, backgroundColor: 'gray' }} />
<ListView
enableEmptySections
dataSource={this.dataSource}
renderRow={this.renderRow2}
/>
</View>
</View>
<Button
onPress={this.changeScreenBack.bind(this)}
title="Tamamlananları Gizle"
color="#841584"
/>
</View>
);
} else
if (this.state.screenSize) {
return (
<View style={container} >
<View style={inputContainer} >
<Icon name={'add'} />
<TextInput
style={inputText}
underlineColorAndroid='transparent'
placeholder="Yapılacak iş ekle..."
placeholderTextColor="#FFFFFF"
value={this.props.todo}
onChangeText={todo => this.props.todoChanged(todo)}
/>
<Button
onPress={this.addToDo.bind(this)}
title="Ekle"
color="#841584"
/>
</View>
<View style={{ flex: 1 }}>
<ListView
enableEmptySections
dataSource={this.dataSource}
renderRow={this.renderRow}
/>
<Button
onPress={this.changeScreen.bind(this)}
title="Tamamlananları Göster"
color="#841584"
/>
</View>
</View>
);
}
}
}
Router.js
import { StackNavigator } from 'react-navigation';
import Todolist from './src/Todolist';
import Profile from './src/Profile';
import TodoDetail from './components/TodoDetail';
import TodoDetailChecked from './components/TodoDetailChecked';
import TodoPage from './components/TodoPage';
const Router = StackNavigator({
Todolist: { screen: Todolist },
TodoDetail: { screen: TodoDetail },
Profile: { screen: Profile },
TodoDetailChecked: { screen: TodoDetailChecked },
TodoPage: { screen: TodoPage }
});
export default Router;
This problem about parent child problem.
Let's quotes from documentation:
It's important to note that this only happens if the screen is
rendered as a route by React Navigation (for example, in response to
this.props.navigation.navigate). For example, if we render
DetailsScreen as a child of HomeScreen, then DetailsScreen won't be
provided with the navigation prop, and when you press the
"Go to Details... again" button on the Home screen, the app will throw one of
the quintessential JavaScript exceptions "undefined is not an object".
To fix your problem is pass this.props.navigation to child component from higher component.
Let's do example:
App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import MyView from './MyView';
import { StackNavigator } from 'react-navigation';
import DetailsScreen from './DetailsScreen';
class App extends React.Component {
render() {
return (
<View style={styles.container}>
<MyView navigation={this.props.navigation} />
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export default StackNavigator({
Home: {
screen: App,
},
Details: {
screen: DetailsScreen,
}
});
MyView.js
import React from 'react';
import { StyleSheet, Text, ListView } from 'react-native';
import TodoDetail from './TodoDetail';
export default class MyView extends React.Component {
constructor() {
super();
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
this.state = {
dataSource: ds.cloneWithRows(['todo 1', 'todo 2']),
};
}
renderRow(todos) {
return <TodoDetail todos={todos} navigation={this.props.navigation} />;
}
render() {
return (
<ListView
enableEmptySections
dataSource={this.state.dataSource}
renderRow={(rowData) => this.renderRow(rowData)}
/>
);
}
}
TodoDetail.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
export default class TodoDetail extends React.Component {
componentDidMount() {
// console.log(this.props.navigation.navigate('Details'));
}
render() {
return (
<View>
<Text>Todo detail</Text>
<Text>{this.props.todos}</Text>
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details', { itemDetail: this.props.todos })}
/>
</View>
);
}
}
DetailsScreen.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default class DetailsScreen extends React.Component {
componentDidMount() {
console.log(this.props.navigation);
}
render() {
const { params } = this.props.navigation.state;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Text>{ params.itemDetail }</Text>
</View>
);
}
}
so in here, you need to pass navigation={this.props.navigation} every child render. If you see MyView component pass navigation props <MyView navigation={this.props.navigation} />.
And inside of it <TodoDetail todos={todos} navigation={this.props.navigation} />, last TodoDetail will available this.props.navigation to access this.props.navigation.navigate.

Undefined is not a object React Navigation

I am trying to navigate from login screen to Tabs screen, But I am getting the following error
Undefined is not an object (evaluating
'this.props.navigation.navigate')
Below is my Login.js:
import React, {Component} from 'react';
import {Text, View, StyleSheet, ImageBackground, Image, TextInput} from 'react-native';
import { Button } from 'react-native-elements'
import firebase from 'firebase';
const textInputConfig = {
placeholderTextColor : '#838383',
}
export default class Login extends Component<{}>{
static navigationOptions = {
header: null
}
login() {
this.props.navigation.navigate('Tabs');
}
render (){
return (
<View style={styles.container}>
<ImageBackground source={require('../resources/images/background_image.png')} style={styles.backgroundImage} >
<Image source={require('../resources/images/app_logo.png')} style={styles.logo}/>
<View style={styles.formContainer}>
<TextInput style={styles.textInput} placeholder='Username'
placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<TextInput style={styles.textInput} placeholder='Email'
placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<TextInput style={styles.textInput} placeholder='Password'
secureTextEntry={true} placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<Button raised title='SIGN UP' buttonStyle={styles.signupButton}
containerViewStyle={styles.signupButtonContainer} onPress={() => this.login()} />
</View>
</ImageBackground>
</View>
);
}
}
.....
Below is my Router.js
import React from 'react';
import { TabNavigator, StackNavigator } from 'react-navigation';
import { Icon } from 'react-native-elements';
import Home from '../screens/Home';
import MyCards from '../screens/MyCards';
import AddCard from '../screens/AddCard';
import Login from '../screens/Login.js';
export const MainScreenNavigator = TabNavigator({
Home: {
screen: Home,
navigationOptions : {
tabBarLabel: 'Home',
tabBarIcon: ({ tintColor }) => <Icon name="account-circle" size={35} color={tintColor} />
},
},
MyCards: {
screen: MyCards,
navigationOptions : {
tabBarLabel: 'My Cards',
tabBarIcon: ({ tintColor }) => <Icon name="list" size={35} color={tintColor} />
},
},
},
{
tabBarPosition: 'bottom',
animationEnabled: true,
tabBarOptions: {
activeTintColor: '#e91e63',
},
},
);
export const AppNavigation = StackNavigator({
LoginScreen: { screen: Login },
Tabs: { screen: MainScreenNavigator},
AddCard: { screen: AddCard }
},
{
headerMode: 'screen'
});
Can someone please tell what I am doing wrong?
Edit Login.js:
import React, {Component} from 'react';
import {Text, View, StyleSheet, ImageBackground, Image, TextInput} from 'react-native';
import { Button } from 'react-native-elements'
import firebase from 'firebase';
const textInputConfig = {
placeholderTextColor : '#838383',
}
export default class Login extends Component<{}>{
static navigationOptions = {
header: null
}
login = () => {
console.log("login function");
this.props.navigation.navigate('Tabs');
}
render (){
return (
<View style={styles.container}>
<ImageBackground source={require('../resources/images/background_image.png')} style={styles.backgroundImage} >
<Image source={require('../resources/images/app_logo.png')} style={styles.logo}/>
<View style={styles.formContainer}>
<TextInput style={styles.textInput} placeholder='Username'
placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<TextInput style={styles.textInput} placeholder='Email'
placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<TextInput style={styles.textInput} placeholder='Password'
secureTextEntry={true} placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<Button raised title='SIGN UP' buttonStyle={styles.signupButton}
containerViewStyle={styles.signupButtonContainer} onPress={this.login} />
</View>
</ImageBackground>
</View>
);
}
}
It has the reference issue!
Replace onPress={() => this.login()} with onPress={this.login.bind(this)}
<Button raised title='SIGN UP' buttonStyle={styles.signupButton}
containerViewStyle={styles.signupButtonContainer} onPress={this.login.bind(this)} />

Categories

Resources