passProps not setting props for ListItem for react-native - react-native

I am using a ListItem onPress to navigate to a different route using the code below.
onPress(item) {
this.props.navigator.push({
component: Areas,
passProps: {
new_id: item.new_id,
}
});
}
_renderItem(item) {
return (
<ListItem item={item} onPress={ () => this.onPress(item) }/>
);
}
However, the this.props.new_id is undefined in the next component.
export default class areas extends Component {
constructor(props) {
super(props);
console.log(" UUUU ");
console.log(this.props.new_id);
}
render(){
return (
<Text style={styles.liText}>AAA {this.props.new_id} BBB</Text>
);
}
AppRegistry.registerComponent('areas', () => areas);
Is there anything I am doing incorrectly?

Actually, I found the answer. I looked in renderScene which was not passing the props properly.
I fixed it in the following way:
Initial:
return React.createElement(route.component, { navigator });
To:
return React.createElement(route.component, { ...this.props, ...route.passProps, route, navigator } )
This seems the pass the props.

Related

Passing Navigator object in renderItem

I'm struggling to make Navigator object visible in List Component.
Here the code explained: as you can see in RootDrawer, I have Concept component. It simply shows a list of items based on a id passed in param.
Each item points to another Concept with another id, but I get
undefined is not an object (evaluating 'navigation.navigate')
when I press on that <RippleButton> with onPress={() => navigation.navigate('Concept',{id:12}). The problem here I'm not passing the Navigation object correctly. How can I solve?
main Navigator drawer
const RootDrawer = DrawerNavigator(
{
Home: {
screen: StackNavigator({
Home: { screen: Home }
})
},
Search: {
screen: StackNavigator({
Cerca: { screen: Search },
Concept: { screen: Concept },
})
}
}
);
Concept component
export default class Concept extends Component {
loading = true
static navigationOptions = ({ navigation,state }) => ({
headerTitle: "",
title: `${navigation.state.params.title}` || "",
})
constructor(props) {
super(props);
}
async componentDidMount(){
}
render() {
const { params } = this.props.navigation.state;
const id = params ? params.id : null;
const { t, i18n, navigation } = this.props;
const Concept = DB.get(id)
return (
<View>
<ScrollView>
<List data={Concept.array|| []} title={"MyTile"} navigation={navigation} />
</ScrollView>
</View>
);
}
}
List Component
class List extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
const { navigation } = this.props;
}
_renderItem = (item,navigation) => (
<RippleButton
id={item.id}
onPress={() => navigation.navigate('Concept', { id: 12, otherParam: 'anything you want here'})}> //this line throws the error
<Text>{item.Term}</Text>
</RippleButton>
)
render() {
const { navigation } = this.props;
return (
<View>
<FlatList
data={this.props.data}
renderItem={({item}) => this._renderItem(item, navigation)}
/>
</View>)
}
}
Instead of passing the navigation prop, you can try using the withNavigation HOC.
Where your List Component is defined:
import { withNavigation } from 'react-navigation`
....
export default withNavigation(List)
Now the List component will have access to the navigation prop

How to pass parameters from parent activity to child tabs in react native?

I am new in react native and looking if someone could direct me in detail how to pass parameters to a child tab.
I researched already and found that it could be done using screenprops, however none of those gave me a clear understanding on how to use it to pass the parameters. A clean sample code could be beneficial.
It is quite easy you have not look around enough there are lots of packages, I recommend you to use following package, and take a look at following example. Next time research information that you need before you ask something.
import React, { Component } from 'react';
import { TabView, TabBar, SceneMap } from 'react-native-tab-view';
import SceneA from './SceneA';
import SceneB from './SceneB';
class Layout extends Component {
constructor(props) {
super(props);
this.state = {
index: 0,
routes: [
{ key: 'active', title: 'Scene A' },
{ key: 'inactive', title: 'Scene B' },
],
};
this.renderScene = this.renderScene.bind(this);
this.renderLabel = this.renderLabel.bind(this);
this.onTabChange = this.onTabChange.bind(this);
}
onTabChange(index) {
this.setState({ index });
}
// Here you can send props to different tab components
renderScene({ route }) {
if (!route.key) return null;
if (route.key === 'active') {
return <SceneA type="active" />; // SceneA specific props here
}
if (route.key === 'inactive') {
return <SceneB type="inactive" />;
}
}
renderLabel({ route }, props) {
const { index } = this.state;
const selected = route.key === props.navigationState.routes[index].key;
return (
<View>
<Text>
{route.title.toUpperCase()}
</Text>
</View>
);
}
renderTab() {
return (
<TabView
navigationState={this.state}
onIndexChange={this.onTabChange}
renderScene={this.renderScene}
renderTabBar={props => (
<TabBar
{...props}
renderLabel={e => this.renderLabel(e, props)}
/>
)}
/>
);
}
render() {
return (
<View>
{this.renderTab()}
</View>
);
}
}
export default Layout;

In a React-Native app, how to use SwitchNavigator (react-navigator) and react-redux?

I'm using react-navigation's SwitchNavigator to manage my navigation based on authentication state. When Authenticated, I want to use Redux to store data I'm fetching.
My SwitchNavigator looks like this
SwitchRouteConfig = {
AuthLoading: AuthLoadingScreen,
Authenticated: AppStackNavigator,
NotAuthenticated: AuthStackNavigator,
}
SwitchConfig = {
initialRouteName: 'AuthLoading',
}
export default createSwitchNavigator(SwitchRouteConfig, SwitchConfig);
My Authenticated navigation looks like this:
// App Bottom Tab Navigator
const AppTabRouteConfig = {
AddItem: { screen: AddItem },
Items: { screen: Items },
Map: { screen: Map },
Help: { screen: Help },
}
const AppTabConfig = { initialRouteName: 'Items',}
const AppTabNavigator = new createBottomTabNavigator(
AppTabRouteConfig,
AppTabConfig)
And in my Screen we have:
class Items extends React.Component {
constructor(props){
super(props);
this.state = {};
}
componentDidMount(){
this.props.getData(); //call our redux action
}
render() {
if(this.props.isLoading){
return(
<View>
<ActivityIndicator />
</View>
)
} else {
return (
<Provider store={store}>
<SafeAreaView>
<FlatList
data={this.props.dataSource.features}
renderItem={({ item }) =>
<TouchableWithoutFeedback>
<View style={styles.listContainer}>
<Text>{item.prop1}</Text>
<Text>{item.prop2}</Text>
</View>
</TouchableWithoutFeedback>
}
/>
</SafeAreaView>
</Provider>
)
}
}
}
function mapStateToProps(state, props) {
return {
isLoading: state.dataReducer.isLoading,
dataSource: state.dataReducer.dataSource
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(Actions, dispatch);
}
export default connect(mapStateToProps,
mapDispatchToProps)(Items)
When I'm not authenticated, that works fine. I can login. When I am authenticated, I get the following error:
Invariant Violation: Could not find "store"
in either the context or props of
Connect(Items)". Either wrap the root
component in a <Provider>, or explicitly pass
"store" as a prop to "Connect(Items)".
In the reading I've done today, all the samples have a single top-level component which they wrap with . So, I'm not understanding how you instantiate the store and manage Redux without that model.
I should mention two additional things:
The initial authenticated app screen worked fine before I started to implement Redux.
I'm not trying to manage the state with Redux, just application data.
Project started with Create-React-Native-App.
Thank you!
You have to wrap the root component (the switch navigator) inside Provider to make the store available to all container components.
const SwitchRouteConfig = {
AuthLoading: AuthLoadingScreen,
Authenticated: AppStackNavigator,
NotAuthenticated: AuthStackNavigator,
}
const SwitchConfig = {
initialRouteName: 'AuthLoading',
}
const Navigator = createSwitchNavigator(SwitchRouteConfig, SwitchConfig);
// You can use a stateless component here if you want
export default class Root extends React.PureComponent {
render() {
return (
<Provider store={store}>
<Navigator />
</Provider >
);
}
}

Navigator not passing parameters to scene

So, I have a simple button (TouchableHighlight) calling the following function:
showMovie() {
this.props.navigator.push({
name: 'MovieScreen',
index: 1,
movie: "terminator"
});
}
It works as expected, pushing the MovieScreen scene defined in a different file.
In the MovieScreen constructor I have:
constructor(props) {
super(props);
console.log(this.props.movie);
}
All I get is "undefined".
I tried with: console.log(this.props.passProps.movie); => undefined.
I tried putting the "movie" parameter in a passProps object => undefined.
I can't seem to pass parameters to a scene. If I print this.props I can't find anywhere the "movie" variable, but this.props is there and it contains the navigator object and everything.
Judging from the examples around the web, I'm doing exactly what thousands of people do, with the difference that mine doesn't work.
What I'm doing wrong?
More details as requested
This is how my app is composed:
index.android.js
HomepageScreen.js
MovieScreen.js
index.android.js
class MovieApp extends Component {
render() {
return (
<Navigator
initialRoute={{ name: 'HomepageScreen', title: 'My Initial Scene', index: 0 }}
renderScene={ this.renderScene }
/>
);
}
renderScene(route, navigator) {
if (route.name == 'HomepageScreen') {
return <HomepageScreen navigator={navigator} />
}
if (route.name == 'MovieScreen') {
return <MovieScreen navigator={navigator} />
}
}
}
HomepageScreen.js
export default class HomepageScreen extends Component {
constructor(props) {
super(props);
var navigator = this.props.navigator;
render() {
return(
<TouchableNativeFeedback onPress={this.showMovie.bind(this)}>
<View style={Style.movieButton}>
<Text style={Style.textStyle1}>Asd</Text>
</View>
</TouchableNativeFeedback>
);
}
showMovie() {
this.props.navigator.push({
name: 'MovieScreen',
index: 1,
movie: "terminator"
});
}
}
MovieScreen.js
export default class MovieScreen extends Component {
constructor(props) {
super(props);
console.log(this.props.movie);
}
.....
Try this:
renderScene(route, navigator) {
if (route.name == 'HomepageScreen') {
return <HomepageScreen navigator={navigator} {...route.passProps} />
}
if (route.name == 'MovieScreen') {
return <MovieScreen navigator={navigator} {...route.passProps} />
}
}
And passing the props like this:
this.props.navigator.push({
name: 'MovieScreen',
index: 1,
passProps: {
movie: "terminator"
}
});

Howto pass data to a other component with react native Navigator

i'm using a Navigator component and want to pass data from a component to a other.
here is some code.
renderScene(route, navigator) {
var routeId = route.id;
if (routeId === 'SplashPage') {
return (
<SplashPage
navigator={navigator} />
);
}
if (routeId === 'Login') {
return (
<Login
navigator={navigator} />
);
}
if (routeId === 'Home') {
return (
<Home
navigator={navigator} />
);
}
....
I want to pass data from login to home when i click on a button for example
this.props.navigator.replace({
id: 'Home',
passProps: {
currentUser: this.user,
}
})
i would like to get the currentUser in the Home Component. I've tried some code that i found but nothing seem to work.
This is whant i want to do :
class Home extends React.Component {
constructor(props){
super(props);
this.currentUser = ????????
}
If anyone can help me with this i would be grateful.
Thanks
You can set up your renderScene method like this:
renderScene={(route, navigator) => {
return React.createElement(route.component, { ...this.props, ...route.passProps, navigator, route } );
}}
And use it like this:
this.props.navigator.replace({
component: Home,
passProps: {
currentUser: this.user,
}
})
And in Home, you can access currentUser like this:
<Text>{ this.props.currentUser }</Text>
Check out this thread for a more detailed example, but that should work for you.