Skip to content

React Native Tutorial #346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 49 commits into from
Dec 4, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
0ab945e
added react native
alexeuler Nov 21, 2016
f1f86c8
android sdk update
alexeuler Nov 21, 2016
866ceff
basic structure
alexeuler Nov 21, 2016
2787240
better logging
alexeuler Nov 21, 2016
76891e7
added basic router
alexeuler Nov 21, 2016
1df8279
some styling and navigation
alexeuler Nov 21, 2016
3a677bc
added api calls
alexeuler Nov 22, 2016
683af69
api posting
alexeuler Nov 22, 2016
b031e1c
added list view styling
alexeuler Nov 22, 2016
3e0718d
sorting
alexeuler Nov 22, 2016
2cbd493
added spinner
alexeuler Nov 22, 2016
817992a
pull to refresh
alexeuler Nov 22, 2016
bd60ef2
button styling
alexeuler Nov 22, 2016
a83657b
allowed react rails for http calls
alexeuler Nov 22, 2016
89ac193
eslint
alexeuler Nov 23, 2016
1687f9e
colors
alexeuler Nov 23, 2016
842956b
flow
alexeuler Nov 23, 2016
e2134de
android support
alexeuler Nov 23, 2016
63f3dd4
first test
alexeuler Nov 24, 2016
7ec655e
refactored hocs into containers
alexeuler Nov 24, 2016
b072e87
added component tests
alexeuler Nov 24, 2016
9885105
sagas first tests
alexeuler Nov 25, 2016
7c209e3
replaced sagas with thunks
alexeuler Nov 25, 2016
a2b83ea
replaced thunks with effects
alexeuler Nov 25, 2016
791c89e
added reducers tests
alexeuler Nov 28, 2016
93301fe
added hocs tests
alexeuler Nov 28, 2016
6a9f6e0
created common bundle
alexeuler Nov 28, 2016
8e9ea6d
added selectors tests
alexeuler Nov 28, 2016
151a6bb
eslint
alexeuler Nov 28, 2016
c4fbad3
flow
alexeuler Nov 28, 2016
0699ae9
moved dispatch out of try
alexeuler Nov 29, 2016
494acb0
migrated to local npm
alexeuler Nov 29, 2016
0aaf9e0
update for compatibility with thunk
alexeuler Nov 29, 2016
a2e7b25
external lib redux-thunk-effects
alexeuler Nov 29, 2016
58807d2
updated name, icon, bundle id, launch screen
alexeuler Nov 29, 2016
b362f08
removed outdated code
alexeuler Nov 29, 2016
223beb5
ios release
alexeuler Nov 29, 2016
889338b
android app icon + https
alexeuler Nov 29, 2016
dad4437
android release
alexeuler Nov 30, 2016
a556fa3
iOS build 2
alexeuler Nov 30, 2016
e90d93b
eslint additions
alexeuler Dec 1, 2016
2297fb9
fixes for review
alexeuler Dec 1, 2016
3dc7796
returned thunk
alexeuler Dec 1, 2016
e083cb9
added readme.md
alexeuler Dec 1, 2016
da7c262
review comments
alexeuler Dec 2, 2016
f4665d5
first docs
alexeuler Dec 2, 2016
2924614
images fix
alexeuler Dec 2, 2016
2cc60cf
redux doc
alexeuler Dec 2, 2016
5bbfb81
Selectors docs
alexeuler Dec 2, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mobile/ReactNativeTutorial/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["react-native"]
}
6 changes: 6 additions & 0 deletions mobile/ReactNativeTutorial/.buckconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

[android]
target = Google Inc.:Google APIs:23

[maven_repositories]
central = https://repo1.maven.org/maven2
2 changes: 2 additions & 0 deletions mobile/ReactNativeTutorial/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ios
android
45 changes: 45 additions & 0 deletions mobile/ReactNativeTutorial/.eslintrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
extends:
- "eslint-config-shakacode"
- "plugin:lodash-fp/recommended"
- "plugin:flowtype/recommended"
plugins:
- "react-native"
- "flowtype"
- "babel"
- "lodash-fp"

env:
node: true
settings:
import/resolver:
node:
extensions:
- ".js"
- ".android.js"
- ".ios.js"
moduleDirectory:
- "."
- "node_modules"
flowtype:
onlyFilesWithFlowAnnotation: true
globals:
__DEV__: true
fetch: true
rules:
new-cap: 0
react/sort-comp: 2
no-console: 2

babel/no-await-in-loop: 1

generator-star-spacing: 0

react-native/no-unused-styles: 2
react-native/split-platform-components: 2
react-native/no-inline-styles: 2
react-native/no-color-literals: 2

react/jsx-filename-extension:
- 1
- extensions: [".js", ".jsx"]
67 changes: 67 additions & 0 deletions mobile/ReactNativeTutorial/.flowconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
[ignore]

# We fork some components by platform.
.*/*[.]android.js

# Ignore templates with `@flow` in header
.*/local-cli/generator.*

# Ignore malformed json
.*/node_modules/y18n/test/.*\.json

# Ignore the website subdir
<PROJECT_ROOT>/website/.*

# Ignore BUCK generated dirs
<PROJECT_ROOT>/\.buckd/

# Ignore unexpected extra @providesModule
.*/node_modules/commoner/test/source/widget/share.js

# Ignore duplicate module providers
# For RN Apps installed via npm, "Libraries" folder is inside node_modules/react-native but in the source repo it is in the root
.*/Libraries/react-native/React.js
.*/Libraries/react-native/ReactNative.js
.*/node_modules/jest-runtime/build/__tests__/.*
.*/node_modules/react/node_modules/.*
.*/node_modules/react-native-experimental-navigation/.*
.*/node_modules/react-native/Libraries/Components/StaticContainer.js

# Json lint doesn't pass flow
.*/node_modules/jsonlint/.*

[include]

[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow
flow/

[options]
module.system=haste

esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable

experimental.strict_type_args=true

munge_underscores=true

module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'

suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe

suppress_type=$FlowIgnore
suppress_comment=\\(.\\|\n\\)*\\$FlowIgnore

suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-2]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-2]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy

unsafe.enable_getters_and_setters=true

[version]
^0.33.0
41 changes: 41 additions & 0 deletions mobile/ReactNativeTutorial/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# OSX
#
.DS_Store

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace

# Android/IJ
#
*.iml
.idea
.gradle
local.properties

# node.js
#
node_modules/
npm-debug.log

# BUCK
buck-out/
\.buckd/
android/app/libs
android/keystores/debug.keystore
19 changes: 19 additions & 0 deletions mobile/ReactNativeTutorial/.jest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Mocking the global.fetch included in React Native
global.fetch = jest.fn();

// Helper to mock a success response (only once)
fetch.mockResponseSuccess = (body) => {
fetch.mockImplementationOnce (
() => Promise.resolve({
json: () => Promise.resolve(body),
text: () => Promise.resolve(JSON.stringify(body)),
})
);
};

// Helper to mock a failure response (only once)
fetch.mockResponseFailure = (error) => {
fetch.mockImplementationOnce(
() => Promise.reject(error)
);
};
1 change: 1 addition & 0 deletions mobile/ReactNativeTutorial/.watchmanconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
73 changes: 73 additions & 0 deletions mobile/ReactNativeTutorial/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
## React Native Tutorial
This is a simple mobile app for posting comments in React Native.
This tutorial shows how to connect to the the https://www.reactrails.com API for a sample microblog.

### Setup
1. Install the latest version of Xcode from AppStore or https://developer.apple.com/download/ (Apple ID required)
2. Install the latest version of Android Studio from https://developer.android.com/studio/index.html
3. Install nvm (Node Version Manager)

```
curl -o- https://github.com/raw/creationix/nvm/v0.32.1/install.sh | bash
```

4. Install NodeJS stable

```
nvm install node
```

5. Install React Native and recommended packages

```
npm install -g react-native-cli
brew install watchman
brew install flow
```

6. Install npm dependencies

```
npm i
```

### Backend API

* Currently connecting by default to https://www.reactrails.com/. Be aware of that!
* The url can be changed app/api/index.js. Keep in mind, that Android emulator is
a separate Virtual Machine with its own localhost binding. To make the api available under emulator,
you have to use ip address of your computer, that could be seen by running `ifconfig` in the shell

### Running IOS
```
react-native run-ios
```

### Running Android
1. Check that installed build tools match gradle config of android project:
- In gradle config (app > android > build.gradle), search `buildToolsVersion`
- Run `android sdk` from bash and find installed build tools version there
2. Run emulator from Android studio or `emulator @<version>` from bash (you can find installed version by running `emulator -list-avds` from bash)
3. From project folder run
```
react-native run-android
```

### Testing
Testing framework uses mocha + enzyme, to run tests type
```
npm test
```

### Linters
This projects uses Eslint with React and React Native rules. To run linters type
```
npm run lint
```


### Flow
This projects uses Eslint with React and React Native rules. To run linters type
```
npm run flow
```
8 changes: 8 additions & 0 deletions mobile/ReactNativeTutorial/__mocks__/mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react';
import _ from 'lodash/fp';

export default (props) => React.createElement(
'Mock',
_.omit('store', props),
props.children,
);
39 changes: 39 additions & 0 deletions mobile/ReactNativeTutorial/__mocks__/mockCall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
class MockCall {
constructor() {
this.queue = [];
}

setMocks(mocks) {
this.queue = mocks;
}

getNextMock() {
if (!this.queue || !this.queue.length) return undefined;
return this.queue.shift();
}

reset() {
this.queue = [];
}
}

const mockCall = new MockCall();

// Mocks calls inside a function under test. This function takes several args and
// stubs the return from call in order of occurence. If no mock were specified
// it returns underfined
export const mockCalls = (...args) => mockCall.setMocks(args);

// Clears all mocks for calls
export const resetMockCalls = () => mockCall.reset();

// The mock call dispatches a fake action to the store with type: 'CALL' and
// function name and args as parameters.
const call = ({ dispatch }) => (f, ...args) => {
dispatch({ type: 'CALL', name: f.name, args });
const mock = mockCall.getNextMock();
const result = typeof mock === 'function' ? mock() : mock;
return f.then ? Promise.resolve(result) : result;
};

export default call;
11 changes: 11 additions & 0 deletions mobile/ReactNativeTutorial/__mocks__/mockThunkMiddleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import call from './mockCall';

export const thunkMiddlewareCreator = (callEffect) =>
({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, callEffect({ dispatch }));
}
return next(action);
};

export default thunkMiddlewareCreator(call);
9 changes: 9 additions & 0 deletions mobile/ReactNativeTutorial/__mocks__/redux-mock-store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import configureMockStore from 'redux-mock-store';
import { initialState as reduxInitialState } from 'ReactNativeTutorial/app/reducers';

import mockThunkMiddleware from './mockThunkMiddleware';

export const createStoreFromState = configureMockStore([mockThunkMiddleware]);
export const initialState = reduxInitialState;

export default () => createStoreFromState(initialState);
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import Add from 'ReactNativeTutorial/app/bundles/comments/components/Add/Add';

import renderer from 'react-test-renderer';

const actions = {
fetch: jest.fn(),
updateForm: jest.fn(),
createComment: jest.fn(),
};

describe('Add', () => {
it('renders correctly', () => {
const props = {
author: 'Alexey',
text: 'Some random comment',
actions,
};
const tree = renderer.create(
<Add {...props} />
);
expect(tree).toMatchSnapshot();
});
});
Loading