Why importing components from other files caused “

2019-09-02 17:48发布

问题:

I'm fairly advanced in iOS Swift language, but very new in react native framework or javascript language. I also have tried to find the right tutorial for stack navigator for hours but I can't find it. I'm currently using this tutorial to learn the basic of react native stack navigation, and would like to split the two screens into their own files. Basically, I want to mimic Swift with its AppDelegate.swift and View Controller's files. But it generates error like this:

Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

That was old error. The new error now:

TypeError: undefined is not an object (evaluating 'this.props.navigation.navigate')

This error is located at:

in HomeScreen (at renderApplication.js:33)

...

Here's my current code. This has been edited according to the solutions.

App.js:

import React from 'react';
import { Button, AppRegistry } from 'react-native';
import { StackNavigator } from 'react-navigation';
import HomeScreen from './HomeScreen';
import ProfileScreen from './ProfileScreen';

export default HomeScreen;

const App = StackNavigator({
  Home: { screen: HomeScreen },
  Profile: { screen: ProfileScreen },
});

AppRegistry.registerComponent("TestProject", () => App);

HomeScreen.js:

import React from 'react';
import { Button } from 'react-native';
import { StackNavigator } from 'react-navigation';

export default class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Welcome',
  };
  render() {
    const { navigate } = this.props.navigation;
    return (
      <Button
        title="Go to Jane's profile"
        onPress={() =>
          navigate('Profile', { name: 'Jane' })
        }
      />
    );
  }
}

ProfileScreen.js:

import React from 'react';
import { Text } from 'react-native';
import { StackNavigator } from 'react-navigation';

export default class ProfileScreen extends React.Component {
  static navigationOptions = {
    title: 'Jane Profile',
  };
  render() {
    const { navigate } = this.props.navigation;
    return (
      <Text>Welcome to Jane profile!</Text>
    );
  }
}

I would greatly appreciate any point out to any error and mistake in my code, as for now I'm completely oblivious to any problems in my code, as I'm learning this by myself. Please help. The first baby steps are always the hardest part every time I learn new language.

In this case, I'm trying to create a home screen with a button that leads to a second screen (profile) with a text in it. I'm also aware that I should be able to extract the name of the profile in the ProfileScreen which the HomeScreen sent, but I hardcoded it right now to make things simple for me to understand the solution.

回答1:

Try this

import React from 'react';
import { StackNavigator } from 'react-navigation';
import HomeScreen from './HomeScreen';
import ProfileScreen from './ProfileScreen';

const App = StackNavigator({
  HomeScreen: { screen: HomeScreen },
  ProfileScreen: { screen: ProfileScreen },
}, {
  initialRouteName: 'HomeScreen',
  headerMode: 'none'
});

export default () => <App />;
  1. The name of the route should be same not mandatory but recommended.
  2. Export the navigation element.
  3. I don't even have a AppRegistry script in my project but it is still working.

If any issue comment that down below! Hope this will fix the issue

Note : This will work in react-navigation version 1.5.11

For react-navigation v2 try this code

import React from 'react';
import { createStackNavigator } from 'react-navigation';
import HomeScreen from './HomeScreen';
import ProfileScreen from './ProfileScreen';

const App = createStackNavigator({
   HomeScreen: { screen: HomeScreen },
   ProfileScreen: { screen: ProfileScreen },
}, {
   initialRouteName: 'HomeScreen',
   headerMode: 'none'
});

export default () => <App />;

Make the navigation script file global to access its props!



回答2:

In react-native we don't register every component using AppRegistry.registerComponent, rather we register the parent component and parent component render child component. The changes that you need is to register the App component and export the HomeScreen and ProfileScreen.

Sample

App.js

...
const App = StackNavigator({
  Home: { screen: HomeScreen },
  Profile: { screen: ProfileScreen },
});
AppRegistry.registerComponent('projectName', () => App)

HomeScreen.js

...
class HomeScreen extends React.Component {
  ...
}
export default HomeScreen;

ProfileScreen.js

...
class ProfileScreen extends React.Component {
  ...
}
export default ProfileScreen;

Hope this will help!