/advanced-react-native-boilerplate

[DEPRECATED] React Native boilerplate including react-navigation, redux, and sagas with example Textile management.

Primary LanguageTypeScript

@textile/advanced-react-native-boilerplate

React Native boilerplate including react-navigation, redux, and sagas with example Textile management. Built using the Textile React Native SDK and runs an IPFS node directly in your app.

This project uses Typescript.

The project setup was inspired by Textile Photos and was used in AirSecure.

How to use.

Clone this repo
git clone git@github.com:textileio/advanced-react-native-boilerplate.git
cd advanced-react-native-boilerplate

Install dependencies

We use Yarn for development and recommend installing it, however, npm alone might work.

yarn install
(cd ios/; pod install)

Run the app

react-native run-ios

Issues

Please add any issues to the react-native-sdk repo.

Adding new screens

You can add new views as React Native components in src/Containers. Take a look at the Home.tsx for how we've structured a basic screen, reading Textile node state information from our Redux state data.

After adding a new view, you'll want to include it in your Navigation object found at src/Navigation/index.ts.

Import your new view,

import <YourView> from '../Containers/<YourViewFile>'

And add it to the Navigator,

const nav = createSwitchNavigator(
  {
    Home,
    <YourView>
  },
  {
    initialRouteName: 'Home'
  }
)

Adding new state information to Redux

We've included one Redux file here, MainRedux, but you can look at the source code for Textile Photos for more advanced Redux handling.

You can trigger a new Redux action with no state changes simply by updating MainRedux, for example,

const actions = {
  nodeStarted: createAction('NODE_STARTED'),
  newNodeState: createAction('NEW_NODE_STATE', (resolve) => {
    return (nodeState: NodeState) => resolve({ nodeState })
  }),
  yourNewEvent: createAction('NEW_EVENT_HAPPENED')
}

Or, you can create an event's payload to update the Redux state with,

const actions = {
  nodeStarted: createAction('NODE_STARTED'),
  newNodeState: createAction('NEW_NODE_STATE', (resolve) => {
    return (nodeState: NodeState) => resolve({ nodeState })
  }),
  yourNewEvent: createAction('NEW_EVENT_HAPPENED', (resolve) => {
    return (message: String) => resolve({ message })
  })
}
...
// update the redux state to store the latest message from yourNewEvent
export interface MainState {
  started: boolean
  nodeState: NodeState
  latestMessage?: string
}
// we don't need to include it in the initialState since latestMessage is an optional

...
// Add a new switch case to process the payload (message string in this case)
    ...
    case getType(actions.yourNewEvent): {
      return { ...state, latestMessage: action.payload.message }
    }
    ...

Use Sagas to trigger other processes from Redux actions

You can use MainSagas to attach advanced processing to new Redux actions.

Again, MainSagas is a simple example for taking each new event and passing it to a function, but look at Textile Photos for advanced redux/saga interaction.

Take every time your new event is fired and run a function,

// Add a new takeLatest to our sagaInit
export function* mainSagaInit() {
  yield takeLatest('NODE_STARTED', nodeStarted)
  yield takeLatest('NEW_NODE_STATE', newNodeState)
  yield takeLatest('NEW_EVENT_HAPPENED', consoleLogNewEvent)
}
...
// Create a function to execute for NEW_EVENT_HAPPENED
export function * consoleLogNewEvent(action: ActionType<typeof MainActions.yourNewEvent>) {
  const { message } = action.payload
  console.info('New event with message: ', message)
}