Permalink
Browse files

Move HelloWorld template to a single index.js entry point

Summary:
This change (initially discussed in react-community/create-react-native-app#26) moves the HelloWorld project template from two nearly identical entry points (`index.android.js` and `index.ios.js`) to a single, minimal `index.js` entry point. The root component is created in `App.js`. This unifies the project structure between `react-native init` and Create React Native App and allows CRNA's eject to use the entry point from the HelloWorld template without any hacks to customize it. Also examples in the docs can be just copy-pasted to `App.js` the same way in both HelloWorld and CRNA apps without having to first learn about  `AppRegistry.registerComponent`.

* Created a new project from the template using `./scripts/test-manual-e2e.sh` and verified that:
  * The app builds, starts and runs both on Android and iOS.
  * Editing and reloading changes works.
  * The new files (`index.js`, `App.js`, `__tests__/App.js`) get created in the project folder.

<img width="559" alt="screen shot 2017-08-01 at 19 10 51" src="https://user-images.githubusercontent.com/497214/28835171-300a12b6-76ed-11e7-81b2-623639c3b8f6.png">
<img width="467" alt="screen shot 2017-08-01 at 19 09 12" src="https://user-images.githubusercontent.com/497214/28835180-33d285e0-76ed-11e7-8d68-2b3bc44bf585.png">

<!--
Thank you for sending the PR!

If you changed any code, please provide us with clear instructions on how you verified your changes work. In other words, a test plan is *required*. Bonus points for screenshots and videos!

Please read the Contribution Guidelines at https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md to learn more about contributing to React Native.

Happy contributing!
-->
Closes #15312

Differential Revision: D5556276

Pulled By: hramos

fbshipit-source-id: 068fdf7e51381c2bc50321522f2be0db47296c5e
  • Loading branch information...
fson authored and facebook-github-bot committed Aug 3, 2017
1 parent f5f5ed5 commit 6e99e314b232c315628c31f97a865c17c071ad23
@@ -230,13 +230,13 @@ function e2e_suite() {
# js tests
if [ $RUN_JS -ne 0 ]; then
# Check the packager produces a bundle (doesn't throw an error)
react-native bundle --max-workers 1 --platform android --dev true --entry-file index.android.js --bundle-output android-bundle.js
react-native bundle --max-workers 1 --platform android --dev true --entry-file index.js --bundle-output android-bundle.js
if [ $? -ne 0 ]; then
echo "Could not build android bundle"
return 1
fi
react-native bundle --max-workers 1 --platform ios --dev true --entry-file index.ios.js --bundle-output ios-bundle.js
react-native bundle --max-workers 1 --platform ios --dev true --entry-file index.js --bundle-output ios-bundle.js
if [ $? -ne 0 ]; then
echo "Could not build iOS bundle"
return 1
View
@@ -583,12 +583,12 @@ Now that you have successfully run the app, let's modify it.
<block class="native mac ios" />
- Open `index.ios.js` in your text editor of choice and edit some lines.
- Open `index.js` in your text editor of choice and edit some lines.
- Hit `⌘R` in your iOS Simulator to reload the app and see your changes!
<block class="native mac android" />
- Open `index.android.js` in your text editor of choice and edit some lines.
- Open `index.js` in your text editor of choice and edit some lines.
- Press the `R` key twice or select `Reload` from the Developer Menu (`⌘M`) to see your changes!
<block class="native windows linux android" />
@@ -597,7 +597,7 @@ Now that you have successfully run the app, let's modify it.
Now that you have successfully run the app, let's modify it.
- Open `index.android.js` in your text editor of choice and edit some lines.
- Open `index.js` in your text editor of choice and edit some lines.
- Press the `R` key twice or select `Reload` from the Developer Menu (`⌘M`) to see your changes!
<block class="native mac ios android" />
@@ -292,15 +292,15 @@ Now we will actually modify the native iOS application to integrate React Native
The first bit of code we will write is the actual React Native code for the new "High Score" screen that will be integrated into our application.
##### 1. Create a `index.ios.js` file
##### 1. Create a `index.js` file
First, create an empty `index.ios.js` file in the root of your React Native project.
First, create an empty `index.js` file in the root of your React Native project.
`index.ios.js` is the starting point for React Native applications on iOS, and it is always required. It can be a small file that `require`s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. In our case, we will just put everything in `index.ios.js`.
`index.js` is the starting point for React Native applications, and it is always required. It can be a small file that `require`s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. In our case, we will just put everything in `index.js`.
##### 2. Add your React Native code
In your `index.ios.js`, create your component. In our sample here, we will add simple `<Text>` component within a styled `<View>`
In your `index.js`, create your component. In our sample here, we will add simple `<Text>` component within a styled `<View>`
```javascript
'use strict';
@@ -358,7 +358,7 @@ AppRegistry.registerComponent('MyReactNativeApp', () => RNHighScores);
#### The Magic: `RCTRootView`
Now that your React Native component is created via `index.ios.js`, you need to add that component to a new or existing `ViewController`. The easiest path to take is to optionally create an event path to your component and then add that component to an existing `ViewController`.
Now that your React Native component is created via `index.js`, you need to add that component to a new or existing `ViewController`. The easiest path to take is to optionally create an event path to your component and then add that component to an existing `ViewController`.
We will tie our React Native component with a new native view in the `ViewController` that will actually host it called `RCTRootView` .
@@ -372,9 +372,9 @@ You can add a new link on the main game menu to go to the "High Score" React Nat
We will now add an event handler from the menu link. A method will be added to the main `ViewController` of your application. This is where `RCTRootView` comes into play.
When you build a React Native application, you use the React Native packager to create an `index.ios.bundle` that will be served by the React Native server. Inside `index.ios.bundle` will be our `RNHighScore` module. So, we need to point our `RCTRootView` to the location of the `index.ios.bundle` resource (via `NSURL`) and tie it to the module.
When you build a React Native application, you use the React Native packager to create an `index.bundle` that will be served by the React Native server. Inside `index.bundle` will be our `RNHighScore` module. So, we need to point our `RCTRootView` to the location of the `index.bundle` resource (via `NSURL`) and tie it to the module.
We will, for debugging purposes, log that the event handler was invoked. Then, we will create a string with the location of our React Native code that exists inside the `index.ios.bundle`. Finally, we will create the main `RCTRootView`. Notice how we provide `RNHighScores` as the `moduleName` that we created [above](#the-react-native-component) when writing the code for our React Native component.
We will, for debugging purposes, log that the event handler was invoked. Then, we will create a string with the location of our React Native code that exists inside the `index.bundle`. Finally, we will create the main `RCTRootView`. Notice how we provide `RNHighScores` as the `moduleName` that we created [above](#the-react-native-component) when writing the code for our React Native component.
<block class="objc" />
@@ -389,7 +389,7 @@ First `import` the `RCTRootView` header.
```objectivec
- (IBAction)highScoreButtonPressed:(id)sender {
NSLog(@"High Score Button Pressed");
NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios"];
NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
RCTRootView *rootView =
[[RCTRootView alloc] initWithBundleURL: jsCodeLocation
@@ -429,7 +429,7 @@ import React
```swift
@IBAction func highScoreButtonTapped(sender : UIButton) {
NSLog("Hello")
let jsCodeLocation = URL(string: "http://localhost:8081/index.ios.bundle?platform=ios")
let jsCodeLocation = URL(string: "http://localhost:8081/index.bundle?platform=ios")
let mockData:NSDictionary = ["scores":
[
["name":"Alex", "value":"42"],
@@ -471,7 +471,7 @@ Wire up the new link in the main menu to the newly added event handler method.
### Test your integration
You have now done all the basic steps to integrate React Native with your current application. Now we will start the React Native packager to build the `index.ios.bundle` package and the server running on `localhost` to serve it.
You have now done all the basic steps to integrate React Native with your current application. Now we will start the React Native packager to build the `index.bundle` package and the server running on `localhost` to serve it.
##### 1. Add App Transport Security exception
@@ -586,15 +586,15 @@ Now we will actually modify the native Android application to integrate React Na
The first bit of code we will write is the actual React Native code for the new "High Score" screen that will be integrated into our application.
##### 1. Create a `index.android.js` file
##### 1. Create a `index.js` file
First, create an empty `index.android.js` file in the root of your React Native project.
First, create an empty `index.js` file in the root of your React Native project.
`index.android.js` is the starting point for React Native applications on Android, and it is always required. It can be a small file that `require`s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. In our case, we will just put everything in `index.android.js`.
`index.js` is the starting point for React Native applications, and it is always required. It can be a small file that `require`s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. In our case, we will just put everything in `index.js`.
##### 2. Add your React Native code
In your `index.android.js`, create your component. In our sample here, we will add simple `<Text>` component within a styled `<View>`:
In your `index.js`, create your component. In our sample here, we will add simple `<Text>` component within a styled `<View>`:
```javascript
'use strict';
@@ -679,7 +679,7 @@ public class MyReactActivity extends Activity implements DefaultHardwareBackBtnH
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.setJSMainModuleName("index")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
@@ -696,7 +696,7 @@ public class MyReactActivity extends Activity implements DefaultHardwareBackBtnH
}
```
> If you are using a starter kit for React Native, replace the "HelloWorld" string with the one in your index.android.js file (it’s the first argument to the `AppRegistry.registerComponent()` method).
> If you are using a starter kit for React Native, replace the "HelloWorld" string with the one in your index.js file (it’s the first argument to the `AppRegistry.registerComponent()` method).
If you are using Android Studio, use `Alt + Enter` to add all missing imports in your MyReactActivity class. Be careful to use your package’s `BuildConfig` and not the one from the `...facebook...` package.
@@ -775,7 +775,7 @@ Now your activity is ready to run some JavaScript code.
### Test your integration
You have now done all the basic steps to integrate React Native with your current application. Now we will start the React Native packager to build the `index.android.bundle` package and the server running on localhost to serve it.
You have now done all the basic steps to integrate React Native with your current application. Now we will start the React Native packager to build the `index.bundle` package and the server running on localhost to serve it.
##### 1. Run the packager
@@ -798,7 +798,7 @@ Once you reach your React-powered activity inside the app, it should load the Ja
You can use Android Studio to create your release builds too! It’s as easy as creating release builds of your previously-existing native Android app. There’s just one additional step, which you’ll have to do before every release build. You need to execute the following to create a React Native bundle, which will be included with your native Android app:
```
$ react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/
$ react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/
```
> Don’t forget to replace the paths with correct ones and create the assets folder if it doesn’t exist.
View
@@ -19,7 +19,7 @@ In accordance with the ancient traditions of our people, we must first build an
```ReactNativeWebPlayer
import React, { Component } from 'react';
import { AppRegistry, Text } from 'react-native';
import { Text } from 'react-native';
export default class HelloWorldApp extends Component {
render() {
@@ -28,12 +28,9 @@ export default class HelloWorldApp extends Component {
);
}
}
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => HelloWorldApp);
```
If you are feeling curious, you can play around with sample code directly in the web simulators. You can also paste it into your `App.js`, `index.ios.js`, or `index.android.js` file to create a real app on your local machine.
If you are feeling curious, you can play around with sample code directly in the web simulators. You can also paste it into your `App.js` file to create a real app on your local machine.
## What's going on here?
@@ -48,14 +45,6 @@ is a built-in component that just displays some text.
So this code is defining `HelloWorldApp`, a new `Component`. When you're building a React Native app, you'll be making new components a lot. Anything you see on the screen is some sort of component. A component can be pretty simple - the only thing that's required is a `render` function which returns some JSX to render.
<div class="banner-crna-ejected">
<h3>Projects With Native Code Only</h3>
<p>
In the particular example above, <code>HelloWorldApp</code> is registered with the <code>AppRegistry</code>. The <code>AppRegistry</code> just tells React Native which component is the root one for the whole application. It's included in these examples so you can paste the whole thing into your <code>index.ios.js</code> or <code>index.android.js</code> file and get it running. If you have a project from Create React Native App, this is handled for you and it's not necessary to call <code>AppRegistry</code> in your code.
</p>
</div>
## This app doesn't do very much
Good point. To make components do more interesting things, you need to [learn about Props](docs/props.html).
@@ -44,6 +44,8 @@ function copyProjectTemplateAndReplace(srcPath, destPath, newProjectName, option
// This also includes __tests__/index.*.js
if (fileName === 'index.ios.js') { return; }
if (fileName === 'index.android.js') { return; }
if (fileName === 'index.js') { return; }
if (fileName === 'App.js') { return; }
}
const relativeFilePath = path.relative(srcPath, absoluteSrcFilePath);
@@ -9,13 +9,13 @@
import React, { Component } from 'react';
import { StackNavigator } from 'react-navigation';
import HomeScreenTabNavigator from './HomeScreenTabNavigator';
import ChatScreen from './chat/ChatScreen';
import HomeScreenTabNavigator from './views/HomeScreenTabNavigator';
import ChatScreen from './views/chat/ChatScreen';
/**
* Top-level navigator. Renders the application UI.
*/
const MainNavigator = StackNavigator({
const App = StackNavigator({
Home: {
screen: HomeScreenTabNavigator,
},
@@ -24,4 +24,4 @@ const MainNavigator = StackNavigator({
},
});
export default MainNavigator;
export default App;

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.
@@ -6,25 +6,31 @@
import React, { Component } from 'react';
import {
AppRegistry,
Platform,
StyleSheet,
Text,
View
} from 'react-native';
export default class HelloWorld extends Component {
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' +
'Cmd+D or shake for dev menu',
android: 'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.android.js
To get started, edit App.js
</Text>
<Text style={styles.instructions}>
Double tap R on your keyboard to reload,{'\n'}
Shake or press menu button for dev menu
{instructions}
</Text>
</View>
);
@@ -49,5 +55,3 @@ const styles = StyleSheet.create({
marginBottom: 5,
},
});
AppRegistry.registerComponent('HelloWorld', () => HelloWorld);
@@ -1,12 +1,12 @@
import 'react-native';
import React from 'react';
import Index from '../index.ios.js';
import App from '../App';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
const tree = renderer.create(
<Index />
<App />
);
});

This file was deleted.

Oops, something went wrong.
@@ -72,6 +72,10 @@ import com.android.build.OutputFile
* ]
*/
project.ext.react = [
entryFile: "index.js"
]
apply from: "../../node_modules/react-native/react.gradle"
/**
@@ -25,6 +25,11 @@ public boolean getUseDeveloperSupport() {
new MainReactPackage()
);
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override

This file was deleted.

Oops, something went wrong.
@@ -0,0 +1,4 @@
import { AppRegistry } from 'react-native';
import App from './App';
AppRegistry.registerComponent('HelloWorld', () => App);
Oops, something went wrong.

0 comments on commit 6e99e31

Please sign in to comment.