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.
git clone git@github.com:textileio/advanced-react-native-boilerplate.git
cd advanced-react-native-boilerplate
We use Yarn for development and recommend installing it, however, npm
alone might work.
yarn install
(cd ios/; pod install)
react-native run-ios
Please add any issues to the react-native-sdk repo.
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'
}
)
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 }
}
...
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)
}