Error when Adjacent elements with react native - javascript

I am very new with react-native and have trouble with this code:
import React, { Component, PropTypes, View } from 'react'
import { connect } from 'react-redux'
import StartupActions from '../Redux/StartupRedux'
import ReduxPersist from '../Config/ReduxPersist'
import { StackNavigator } from 'react-navigation'
import WelcomeContainer from '../Containers/WelcomeContainer'
import SettingsContainer from '../Containers/SettingsContainer'
import About from '../Components/About'
import { Header } from 'react-native-elements'
const AppNavigator = StackNavigator({
Home: {
screen: WelcomeContainer,
navigationOptions: {
title: 'Multi Language Sample App' // we advice using something static like your app's name or company name on the startup screen
}
},
Settings: {
screen: SettingsContainer,
navigationOptions: ({navigation}) => ({
title: navigation.state.params.title
})
},
About: {
screen: About,
navigationOptions: ({navigation}) => ({
title: navigation.state.params.title
})
}
})
class RootContainer extends Component {
componentDidMount() {
if (!ReduxPersist.active) {
this.props.startup()
}
}
render() {
return (
<View>
<AppNavigator />
<AppNavigator />
</View>
)
}
}
const mapStateToDispatch = dispatch => ({
startup: () => dispatch(StartupActions.startup())
})
export default connect(null, mapStateToDispatch)(RootContainer)
RootContainer.propTypes = {
startup: PropTypes.func.isRequired
}
I get the error : Adjacent JSX elements must be wrapped in an enclosing tag.
I found different posts with the same issue but was not able to solve my problem.

Enclose you code inside view or another parent element.
render() {
return (
<View>
<AppNavigator />
<Button
large
icon={{name: 'envira', type: 'font-awesome'}}
title='LARGE WITH RIGHT ICON' />
</View>
)
}
}

In react you need to return a single component/element in your render method.
render() {
return (
<View>
<AppNavigator />
<Button
large
icon={{name: 'envira', type: 'font-awesome'}}
title='LARGE WITH RIGHT ICON'
/>
</View>
)
}
}
Since v0.16 of react you can return an array of elements/components. More info here.
New render return types: fragments and strings You can now return an
array of elements from a component’s render method. Like with other
arrays, you’ll need to add a key to each element to avoid the key
warning
render() {
return (
[<AppNavigator />, <Button large icon={{name: 'envira', type: 'font-awesome'}} title='LARGE WITH RIGHT ICON' />]
)
}
}

Related

react-native : How to pass state to nested stackNavigator to tabNavigator

I am trying to use pass state from nested stackNavigator to tabNavigator.
First of all My App.js navigation structure looks like this
App.js
//tabNavigator. This is where I want to pass my state.
const tabNavigator = createMaterialTopTabNavigator({
tabOne:tabOne,
tabTwo: tabTwo,
tabThree:tabThree
})
//I nested tabNavigator to this StackNavigator
const StackNavigator = createStackNavigator({
stackAndTab: {
screen: tabNavigator,
navigationOptions: ({ navigation }) => ({
header:
<CustomHeader
navigation={navigation}
/>
,
})
},
}, {
defaultNavigationOptions: {
header: null
}
})
//I have another stackNavigator where I put all my stackNavigators.
const AllStackNavigator = createStackNavigator(
{
InitialScreen:InitialScreen,
StackNavigator:StackNavigator,
},
{
defaultNavigationOptions: {
header: null,
},
},
);
//Finally I nest my StackNavigator to SwitchNavigator
const SwitchNavigator = createSwitchNavigator(
{
AllStackNavigator:AllStackNavigator
},
{
defaultNavigationOptions: {
header: null,
},
},
);
const CombinedNavigator = createAppContainer(StartSwitchNavigator);
export default class App extends React.Component {
render() {
return <CombinedNavigator/>;
}
}
I am trying to pass state to the StackNavigator from the InitialScreen like this:
export default class InitialScreen extends React.Component {
constructor(props) {
super(props)
this.state = {
newState:'this is new State'
}
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity
onPress={()=> this.props.navigation.navigate('StackNavigator', {state:'this.state.newState})}
style={{width:'100%', height:110}}>
<Text>pass state</Text>
</TouchableOpacity>
</View>
);
}
}
My Question
How can I access the passed state newState(the state that I passed from initialScreen) in the tabNavigator where tabOne, tabTwo, tabThree is nested.
I saw your problem and I feels your code is little bit in a chaos. you can use this line for getting params which you are pass to StackNavigator.
try this code in your Tab Screens
this.props.navigation.dangerouslyGetParent().getParam('state')
and please correct your onPress event
onPress={()=> this.props.navigation.navigate('StackNavigator', {state:this.state.newState})}

Native Base Toast - TypeError: TypeError: TypeError: null is not an object (evaluating 'this.toastInstance._root.getModalState')

I am using react native to build a mobile app. I am facing a Nativ Base Toast issue. When I first load application and then navigate to ticket status, if I go back to a home page with an android back button, following error popup.
Below are my code and error screenshot.
NOTE - This error does not come every time.
Any help would be appreciated.
Thanks in advance
Home.js code (render at application load)
import React, { Component } from 'react';
import { createDrawerNavigator , tabBarOptions, StackNavigator} from 'react-navigation';
import Header from './Header';
import Request from './Request';
import Navigation from './Navigation';
import TicketStatus from './TicketStatus/TicketStatus';
const RootStack = StackNavigator(
{
Home: { screen: Request },
Navigation: { screen: Navigation },
TicketStatus: { screen: TicketStatus },
},
{
headerMode: 'none',
navigationOptions: {
headerVisible: false,
}
}
);
RootStack.navigationOptions = {
header: null
}
export default RootStack;
TicketStatus.js code
export default class TicketStatus extends Component {
constructor(props){
super(props)
this.state = {
allTickets : [{ name:'Jones Residence', number: '12343534325', classs:'active'},{name:'Rex Bell Elementary', number: '12343534325', classs:'pending' },{name:'CitiBank Offic', number: '123435', classs:'expired' }]
};
}
_fetchTickets(token)
{
if(this.mounted) {
this.setState({
isloading: true
});
}
fetch(config.BASE_URL+'alltickets?api_token='+token,{
method: 'GET',
headers: {
'Authorization': 'Bearer ' + token,
}
})
.then((response) => response.json())
.then((res) => {
if(this.mounted) {
if(res.status == 1)
{
this.setState({
allTickets: res.data,
});
}
else if(res.status == 0)
{
Toast.show({
text: res.message,
buttonText: "Okay",
duration: 5000,
type: "danger"
})
}
this.setState({
isloading: false,
});
}
}).catch(err => {
if(this.mounted) {
Toast.show({
text: err,
buttonText: "Okay",
duration: 5000,
type: "danger"
})
}
}).done();
}
componentDidMount(){
this.mounted = true;
this._fetchTickets(config.token);
}
componentWillUnmount(){
this.mounted = false;
Toast.hide();
Toast.toastInstance = null;
}
renderTickets = () => {
return (
<Content style={{height:300, backgroundColor:"#FFBC42", borderRadius:10}}>
<ScrollView>
{
this.state.allTickets.map((option, i) => {
return (
<TouchableOpacity key={i} >
<View>
<Text>{option.number} / {option.name}</Text>
</View>
</TouchableOpacity>
)
})
}
</ScrollView>
</Content>
)
}
render() {
return (
<Root>
<Container>
<Header {...this.props}/>
<ScrollView>
<Content padder>
<H1 style={styless.ticket_req}>Check the Status of a Ticket</H1>
{this.renderTickets()}
</Content>
</ScrollView>
{this.state.isloading && (
<Loader />
)}
</Container>
</Root>
);
}
}
For Toast to work, you need to wrap your topmost component inside <Root> from native-base.
<Root>
<AppNavigator />
</Root>
Which version of NativeBase are you using? It seems like this error might have been resolved in a newer release. See https://github.com/GeekyAnts/NativeBase/issues/1790
it is only necessary to enclose the entire component in
<Root>
<Container>
<Header />
<Content padder>
<Button onPress={() => Toast.show({
text: 'Wrong password!',
buttonText: 'Okay'
})}>
<Text>Toast</Text>
</Button>
</Content>
</Container>
</Root>
There is a temporary fix for this.
Replace native-base in your package.json with:
"native-base": "https://github.com/dansokol/NativeBase.git",
Gotten from https://github.com/GeekyAnts/NativeBase/issues/3109
in functional component
import { Root } from 'native-base';
then
return(
<Root>
...
{renderToast}
</Root>
)
I have encountered the same error today and here is how I have solved it.
First ensure that you have wrapped your App Root(a.k.a Your Final UI component) in NativeBase's Root component as shown below:
import 'react-native-gesture-handler';
import React from 'react';
import { AppNavigator } from './navigation.component';
import { Root } from "native-base";
//AppNavigator: https://reactnavigation.org/docs/2.x/app-containers/
//You can replace it with the <Something/> below #3, depending on your project
export default () => (
<Root>
<AppNavigator/>
</Root>
);
If you are using other libraries, e.g UIKitten that demand to be root. Just do as shown below:
import 'react-native-gesture-handler';
import React from 'react';
import {
ApplicationProvider,
IconRegistry,
} from '#ui-kitten/components';
import { EvaIconsPack } from '#ui-kitten/eva-icons';
import * as eva from '#eva-design/eva';
import { AppNavigator } from './navigation.component';
import { Root } from "native-base";
export default () => (
<React.Fragment>
<IconRegistry icons={EvaIconsPack}/>
<ApplicationProvider {...eva} theme={eva.light}>
<Root>
<AppNavigator/>
</Root>
</ApplicationProvider>
</React.Fragment>
);
Second, create a function and put it a file eg MyOwnToast.js, as shown below: (filename: MyOwnToast.js ).
import {Toast as ToastNB} from 'native-base';
class Toast extends ToastNB {}
export default Toast;
In the file that you want to render and show the toast. Do the following
import React from 'react';
import { View, Button } from 'react-native';
import {Toast} from './MyOwnToast.js';
class Something extends React.Component{
constructor(){
super();
}
openTheToast = ()=>{
Toast.show({
text: 'Voila! Here is the toast.',
buttonText: 'Okay',
duration: 3000,
position: 'top',
type: 'success',
});
}
render(){
return(<View>
<Toast
ref={(c) => {
if (c) Toast.toastInstance = c;
}}
/>
<Button onPress={()=>this.openTheToast()}> Open The Toast </Button>
</View>)
}
};
export default Something;
These steps should solve it for you.

Creating a function that returns a component in React

I want to create a function that returns a component similar to how React Navigation does:
const AppNavigator = StackNavigator({
Room: { screen: RoomContainer },
Game: {
screen: GameContainer,
navigationOptions: {
gesturesEnabled: false
}
},
Catalog: { screen: CatalogContainer }
}, {
headerMode: 'none',
mode: 'modal'
})
Which you can then use like:
<AppNavigator />
I have looked at their code but still a bit confused. This is my simple example.
import onboardingCreator from 'this-package'
export default class App extends Component {
render() {
let Onboard = onboardingCreator({
test: 'cool'
})
console.log("OB", Onboard)
return (
<Onboard />
);
}
}
And then in another file:
export default (props) => {
console.log("PROPS", props)
return <View style={{backgroundColor: 'green', flex: 1}} />
}
Where am I going wrong? I just need a simple example to get me in the right direction I think :)
Thanks.
The problem is that your function is returning an instance of a component, not the definition of the component class. If you want to render the instance (the way the function works now), it would look more like this:
import onboardingCreator from 'this-package'
export default class App extends Component {
render() {
let onboard = onboardingCreator({
test: 'cool'
})
console.log("OB", onboard)
return <div>{onboard}</div>;
}
}
If, on the other hand, you want to create a new component and return it, it would look more like this:
export default (props) => {
console.log("PROPS", props)
class GeneratedComponent extends Component {
render() {
return <View
{...props}
style={{backgroundColor: 'green', flex: 1}}
/>;
}
}
return GeneratedComponent;
}

undefined is not an object error in react native

I'm trying to create a route to a screen by pressing a button in a side menu using react navigation. When I try to implement it, I get the following error:
undefined is not an object (evaluating '_this.props.user.Range')
The error flags, point something wrong in here:
RangeValues: this.props.user.Range
The rest of the components I am trying to navigate to are here:
import React, {Component} from 'react'
import {
StyleSheet,
View,
Text,
Switch,
} from 'react-native'
import Slider from 'react-native-multislider'
export default class Profile extends Component {
state = {
RangeValues: this.props.user.Range,
distanceValue: [this.props.user.distance]
}
render() {
const {name, work, id} = this.props.user
const {RangeValues, distanceValue} = this.state
return (
<View style={styles.container}>
<View style={styles.profile}>
<Text style={{fontSize:20}}>{name}</Text>
</View>
<View style={styles.label}>
<Text>Distance</Text>
<Text style={{color:'darkgrey'}}>{distanceValue}km</Text>
</View>
<Slider
min={1}
max={100}
values={distanceValue}
onValuesChange={val => this.setState({distanceValue:val})}
onValuesChangeFinish={val => this.updateUser('distance', val[0])}
/>
<View style={styles.label}>
<Text>Age Range</Text>
<Text style={{color:'darkgrey'}}>{ageRangeValues.join('-')}</Text>
</View>
<Slider
min={1}
max={200}
values={RangeValues}
onValuesChange={val => this.setState({RangeValues:val})}
onValuesChangeFinish={val => this.updateUser('Range', val)}
/>
</View>
)
}
}
I want to navigate from a button in a drawer using stack navigator, my routing is as follows:
import { StackNavigator } from 'react-navigation';
import React from 'react';
import Home from './screens/home';
import Login from './screens/login';
import Profile from './screens/profile';
const RouteConfigs = {
Login: { screen: Login },
Home: { screen: Home },
Profile: { screen: Profile },
};
const StackNavigatorConfig = {
headerMode: 'none',
}
export default StackNavigator(RouteConfigs, StackNavigatorConfig)
Where I am trying to navigate from is the Home screen component. The function I have used for this within the Home component is:
() => this.props.navigation.navigate('Profile', { user: this.state.user })
Does anybody know how to fix this error in order for me to navigate from the home component to the profile component?
I think you should bind your props from constructor :
export class MyClass extends Component {
constructor(props) {
super(props);
if (!this.state) {
this.state = {
data: props.myData
}
}
render() {DO THE JOB HERE}
}
}
Then you can access to this.state instead of state
For more explanations, props are not yet available since the constructor has not pass. See Component doc : https://facebook.github.io/react/docs/react-component.html#constructor

render component based on state in react native

I am using react-native-side-menu for the menu in the app. Since this module using state to control the clicked menu, I would like to used it to render the component as well.
I am referred to this solution But it is not working, I got
Expected a component class, got [object Object].
This is what I did:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
} from 'react-native';
import Menu from './menu';
import SideMenu from 'react-native-side-menu';
import First from './first';
import Second from './second';
module.exports = class Main extends Component {
state = {
isOpen: false,
selectedItem: 'First',
};
toggle() {
this.setState({
isOpen: !this.state.isOpen,
});
}
updateMenuState(isOpen) {
this.setState({ isOpen, });
}
onMenuItemSelected = (item) => {
this.setState({
isOpen: false,
selectedItem: item,
});
}
render() {
const menu = <Menu onItemSelected={this.onMenuItemSelected} />;
return (
<SideMenu
menu={menu}
isOpen={this.state.isOpen}
onChange={(isOpen) => this.updateMenuState(isOpen)}
>
<this.state.selectedItem />
<Button style={styles.button} onPress={() => this.toggle()}>
<Image
source={require('./assets/menu.png')} style={{width: 32, height: 32}} />
</Button>
</SideMenu>
);
}
}
....
UPDATE
Thanks for #NaderDabit suggest. Yes indeed, I should use
selectedItem: <First />,
instead.

Categories

Resources