Convert Figma logo to code with AI

bartonhammond logosnowflake

:snowflake: A React-Native Android iOS Starter App/ BoilerPlate / Example with Redux, RN Router, & Jest with the Snowflake Hapi Server running locally or on RedHat OpenShift for the backend, or a Parse Server running locally or remotely on Heroku

4,592
614
4,592
17

Top Related Projects

React Native starter kit with over 40 screens and modern Light and Dark theme for creating stunning cross-platform mobile applications.

An example app with all the UI components of NativeBase

17,543

Infinite Red's battle-tested React Native project boilerplate, along with a CLI, component/model generators, and more!

Cross-Platform React Native UI Toolkit

A complete native navigation solution for React Native

Customizable Icons for React Native with support for image source and full styling.

Quick Overview

Snowflake is a React Native boilerplate project that provides a comprehensive starting point for building cross-platform mobile applications. It includes a robust architecture, state management, authentication, and various other features to help developers quickly bootstrap their React Native projects.

Pros

  • Comprehensive setup with Redux for state management and React Navigation for routing
  • Includes authentication flow and API integration out of the box
  • Follows best practices and provides a scalable architecture for React Native apps
  • Comes with pre-configured testing setup using Jest

Cons

  • May be overwhelming for beginners due to its extensive feature set
  • Some dependencies might become outdated over time if not regularly maintained
  • Opinionated structure might not fit all project requirements
  • Learning curve for developers unfamiliar with the included libraries and patterns

Code Examples

  1. Redux action creator:
export function loginRequest(email, password) {
  return {
    type: LOGIN_REQUEST,
    payload: {
      email,
      password
    }
  };
}
  1. React Native component with Redux connection:
import React from 'react';
import { View, Text } from 'react-native';
import { connect } from 'react-redux';

const ProfileScreen = ({ user }) => (
  <View>
    <Text>Welcome, {user.name}!</Text>
  </View>
);

export default connect(state => ({
  user: state.auth.user
}))(ProfileScreen);
  1. API service example:
import { API_BASE_URL } from '../config';

export async function login(email, password) {
  const response = await fetch(`${API_BASE_URL}/auth/login`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ email, password }),
  });
  return response.json();
}

Getting Started

  1. Clone the repository:

    git clone https://github.com/bartonhammond/snowflake.git
    cd snowflake
    
  2. Install dependencies:

    npm install
    
  3. Run the app:

    npx react-native run-ios
    # or
    npx react-native run-android
    
  4. Start developing your app by modifying the existing components and adding new ones in the src directory.

Competitor Comparisons

React Native starter kit with over 40 screens and modern Light and Dark theme for creating stunning cross-platform mobile applications.

Pros of KittenTricks

  • More comprehensive UI components and screens
  • Better documentation and examples
  • Active development and regular updates

Cons of KittenTricks

  • Larger project size and potentially more complex setup
  • Less focus on state management and backend integration
  • May require more customization for specific use cases

Code Comparison

Snowflake (Redux setup):

import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import reducer from '../reducers'

const createStoreWithMiddleware = applyMiddleware(thunk)(createStore)
const store = createStoreWithMiddleware(reducer)

KittenTricks (UI component):

import React from 'react'
import { Button, Text } from '@ui-kitten/components'

export const MyButton = (props) => (
  <Button {...props}>
    <Text>BUTTON</Text>
  </Button>
)

Both projects are React Native boilerplates, but they have different focuses. Snowflake emphasizes a robust architecture with Redux integration, while KittenTricks provides a rich set of UI components and screens. Snowflake might be better for developers who need a solid foundation for state management and backend integration, whereas KittenTricks is ideal for those prioritizing UI development and rapid prototyping. The choice between the two depends on the specific requirements of your project and your development preferences.

An example app with all the UI components of NativeBase

Pros of NativeBase-KitchenSink

  • Extensive collection of UI components and examples
  • Regular updates and active maintenance
  • Strong focus on customization and theming

Cons of NativeBase-KitchenSink

  • Larger bundle size due to comprehensive component library
  • Steeper learning curve for beginners
  • Less emphasis on app architecture and state management

Code Comparison

NativeBase-KitchenSink:

import React from 'react';
import { Container, Header, Content, Button, Text } from 'native-base';

export default function App() {
  return (
    <Container>
      <Header />
      <Content>
        <Button><Text>Click Me!</Text></Button>
      </Content>
    </Container>
  );
}

Snowflake:

import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';

const App = ({ dispatch }) => (
  <View>
    <TouchableOpacity onPress={() => dispatch({ type: 'SOME_ACTION' })}>
      <Text>Click Me!</Text>
    </TouchableOpacity>
  </View>
);

export default connect()(App);

NativeBase-KitchenSink focuses on providing a rich set of pre-built components, while Snowflake emphasizes a more minimal approach with Redux integration for state management. NativeBase-KitchenSink is ideal for rapid UI development, whereas Snowflake provides a solid foundation for building scalable apps with a focus on architecture and state management.

17,543

Infinite Red's battle-tested React Native project boilerplate, along with a CLI, component/model generators, and more!

Pros of Ignite

  • More actively maintained with frequent updates
  • Larger community and ecosystem of plugins
  • Comprehensive CLI for project scaffolding and generation

Cons of Ignite

  • Steeper learning curve due to more features and options
  • Potentially more opinionated structure, which may not suit all projects
  • Heavier boilerplate compared to Snowflake's minimalist approach

Code Comparison

Snowflake (App.js):

import React, {Component} from 'react'
import {View} from 'react-native'
import {Router} from 'react-native-router-flux'

class App extends Component {
  render () {
    return (
      <View style={{flex: 1}}>
        <Router scenes={scenes} />
      </View>
    )
  }
}

Ignite (App.tsx):

import React from 'react'
import { useColorScheme } from 'react-native'
import { SafeAreaProvider, initialWindowMetrics } from 'react-native-safe-area-context'
import { NavigationContainer, DefaultTheme, DarkTheme } from '@react-navigation/native'
import { createNativeStackNavigator } from '@react-navigation/native-stack'

export const App = () => {
  const colorScheme = useColorScheme()
  return (
    <SafeAreaProvider initialMetrics={initialWindowMetrics}>
      <NavigationContainer theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
        {/* Navigation stack setup */}
      </NavigationContainer>
    </SafeAreaProvider>
  )
}

Cross-Platform React Native UI Toolkit

Pros of React Native Elements

  • Comprehensive UI toolkit with a wide range of pre-built components
  • Active community and regular updates
  • Customizable themes and styles for consistent design

Cons of React Native Elements

  • Larger package size due to extensive component library
  • May require additional configuration for some advanced use cases
  • Learning curve for customizing complex components

Code Comparison

Snowflake (Login component):

<FormButton
  isDisabled={!this.props.auth.form.isValid || this.props.auth.form.isFetching}
  onPress={this.onPress}
  buttonText={I18n.t('Login.login')}
/>

React Native Elements (Button component):

<Button
  title="Login"
  loading={this.state.loading}
  disabled={!this.state.isValid}
  onPress={this.handleLogin}
  buttonStyle={styles.loginButton}
/>

Both repositories provide React Native components, but React Native Elements offers a more extensive set of pre-built UI elements. Snowflake focuses on providing a complete app structure with authentication and state management, while React Native Elements concentrates on delivering a comprehensive UI toolkit. The code comparison shows similar button implementations, with React Native Elements offering more built-in styling options.

A complete native navigation solution for React Native

Pros of react-native-navigation

  • More comprehensive and feature-rich navigation solution
  • Better performance due to native implementation
  • Extensive documentation and community support

Cons of react-native-navigation

  • Steeper learning curve compared to simpler solutions
  • More complex setup and configuration process
  • Potential compatibility issues with certain React Native versions

Code Comparison

react-native-navigation:

Navigation.setRoot({
  root: {
    stack: {
      children: [
        {
          component: {
            name: 'Home'
          }
        }
      ]
    }
  }
});

snowflake:

<Router>
  <Scene key="root">
    <Scene key="home" component={Home} title="Home" initial={true} />
  </Scene>
</Router>

react-native-navigation offers a more declarative approach to navigation setup, while snowflake uses a component-based structure. The former provides more granular control over navigation behavior, but may require more code for complex scenarios.

react-native-navigation is better suited for large-scale applications with complex navigation requirements, while snowflake provides a simpler solution for smaller projects or those prioritizing ease of use. The choice between the two depends on project size, performance needs, and developer familiarity with each library's paradigms.

Customizable Icons for React Native with support for image source and full styling.

Pros of react-native-vector-icons

  • Extensive icon library with multiple icon sets
  • Easy customization of icon size, color, and style
  • Regular updates and active community support

Cons of react-native-vector-icons

  • Focused solely on icons, not a full app boilerplate
  • May require additional setup for custom icon integration
  • Potential performance impact when using many icons

Code Comparison

react-native-vector-icons:

import Icon from 'react-native-vector-icons/FontAwesome';

const MyComponent = () => (
  <Icon name="rocket" size={30} color="#900" />
);

Snowflake:

import React from 'react';
import { View, Text } from 'react-native';

const MyComponent = () => (
  <View>
    <Text>Hello, Snowflake!</Text>
  </View>
);

Summary

react-native-vector-icons is a specialized library for adding and customizing icons in React Native applications. It offers a wide range of icon sets and easy customization options. However, it focuses solely on icons and may require additional setup for custom icons.

Snowflake, on the other hand, is a more comprehensive boilerplate for React Native apps. It provides a full project structure and includes various features beyond just icons. While it may not offer the same extensive icon library as react-native-vector-icons, it provides a more complete starting point for app development.

The choice between these repositories depends on the specific needs of your project. If you primarily need a robust icon solution, react-native-vector-icons is an excellent choice. For a more comprehensive app starter kit, Snowflake might be more suitable.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Snowflake snowflake

A React-Native starter mobile app, or maybe just an example, or maybe a boilerplate (you decide) for iOS and Android with a single code base, with 2 backends to chose from: a Hapi or Parse Server solution- Demo

JavaScript Style Guide Codacy Badge Join the chat at https://gitter.im/bartonhammond/snowflake License React Native

Installation

Install Snowflake

  • Clone snowflake: git clone https://github.com/bartonhammond/snowflake.git

  • install dependencies

cd snowflake

npm install

Using Snowflake Hapi Server

Use the local or remote Snowflake Hapi Server

To make things easy for you, the config.example.js has been initialized to use the remote Snowflake Hapi Server which is running on Redhat OpenShift.

This Snowflake Hapi Server is Open Source. It can run either locally or on RedHat OpenShift. For your convince a server is running at: https://snowflakeserver-bartonhammond.rhcloud.com

Please refer to https://github.com/bartonhammond/snowflake-hapi-openshift for more information about the code and instructions for installation and setup of the server.

The following commands are for the client

  • Copy the src/lib/config.example.js to src/lib/config.js.
  • Note: the .gitignore includes config.js from being committed to GitHub
  • Note: you must select either hapiLocal or hapiRemote for the backend as shown below with hapiRemote set as the default.
  backend: {
    hapiLocal: false,
    hapiRemote: true,
    parseLocal: false,
    parseRemote: false
  },
  • To run Hapi locally, follow the instructions at https://github.com/bartonhammond/snowflake-hapi-openshift. You will have to install MongoDB and Redis.
  • Note: The default is to run remotely on the RedHat OpenShift Snowflake Server so there is nothing more to do if you want to use it! In that case, just use the config.js as is.
  • If you want to install and run the Snowflake Hapi Server locally, then update the src/lib/config.js file as shown below.
  • Note: use the ip from the ifconfig command for the local. This ip matches the Snowflake Hapi Server setup.
  • An example of the url is shown below assuming the ifconfig shows the local ip to be 192.168.0.5
  • Note: You don't have to provide the local.url value if you are using the remote
  HAPI: {
    local: {
      url: 'http://192.168.0.5:5000'
    },
    remote: {
      url: 'https://snowflakeserver-bartonhammond.rhcloud.com/'
    }
  }

Using Parse Server

This Snowflake Parse Heroku Server is Open Source. It can run either locally or on Heroku. For your convince a server is running at: https://snowflake-parse.herokuapp.com/parse

Please refer to https://github.com/bartonhammond/snowflake-parse-heroku for more information about the code and instructions for installation and setup of the server.

The following instructions are for the client

  • Copy the src/lib/config.example.js to src/lib/config.js.
  • Note: the .gitignore includes config.js from being committed to GitHub
  • Set parseLocal to true if you are running a local instance of parse-server
  • Otherwise, set parseRemote to true to indicate your parse server instance is hosted in the cloud
  backend: {
    hapiLocal: false,
    hapiRemote: false,
    parseLocal: true,
    parseRemote: false
  },
  PARSE: {
    appId: 'snowflake',                              // match APP_ID in parse-server's index.js
    local: {
    	url: 'http://localhost:1337/parse'             // match SERVER_URL in parse-server's index.js
    },
    remote: {
    	url: 'https://enter_your_snowflake_host.com'   // match SERVER_URL in parse-server's index.js
    }
  }

To run:

  • For iOS, from the command line, run via command: react-native run-ios or open XCode and load project, Run Product -> Run (⌘+R)
  • For Android, from the command line, run via the command: react-native run-android assuming you have an emulator or device running and attached
  • To run Jest, npm test
  • To debug Jest unit cases, install node_inspector and run npm run test-chrome
  • Enjoy!


Notes

Code is written to JS Standard and validated with Eslint. To setup your favorite editor using the Eslint configuration, see Editors

Navigation is handled with React Native Router Flux. Multiple scenes support Login, Register, and Reset Password. Once successfully logged in, there are 3 more scenes: Logout, Subview, and Profile.

A user can change their Email Address and User Name once they are logged in using the Profile form.

The icons used throughout the app are from React Native Vector Icons, namely using FontAwesome

Form building is extremely easy and consistent by using Tcomb Form Library by using domain models and writing less code.

Using Redux and Immutable, the state of the application is testable with Jest, which includes Snapshot tests currently with 85 tests and ~90% coverage!!!

To ease the pain of Redux Action definitions, Snowflake uses Key Mirror.

Using the Validate.JS Library, all user input is validated. Appropriate messages are displayed to the user guiding them in the input requirements.

Once a user is logged in, their Session State is stored in AsyncStorage so that subsequent usage does not require logging in again.

Snowflake supports multiple languages using I18n with English, French and Spanish.

Snowflake supports Hot Reloading of its state.

Snowflake uses CI with Bitrise.io and has extensive docs and 45+ min of video demonstating implementation.

Snowflake has a choice of servers, either


Content


Editor Configuration

Atom

apm install editorconfig es6-javascript javascript-snippets linter linter-eslint language-babel

Sublime

Others

Screens

PlatformRegisterLoginProfile
iOSiOS ProfileiOS LoginiOS Register
AndroidAndroid RegisterAndroid LoginAndroid Profile

Summary

  1. The application runs on both iOS and Android with a single code base
  2. A User can Register, Login, Logout, Reset their Password and modify their Profile
  3. The Forms display messages for help and field validation.
  4. The Forms are protected when fetching.
  5. The Forms display spinner when fetching.
  6. Form submission errors are displayed (see above Login)
  7. All state changes* are actions to the Redux store.
  8. The backend is provided by either a Hapi server or Parse server using the Rest API
  9. Every action performed by the UI interfaces with the Redux actions and subsequently to the Redux Store. This reduces the complexity of the JSX Components tremendouslyand makes them easily testable.
  10. Jest Unit Tests cover ~90% of the application statements.
  11. Demonstrates how to setup React-Native to perform Jest testing with Mock modules
  12. Includes ability to debug Jest unit tests with Chrome
  13. Instructions and videos for continuous integration with Bitrise.io

Quotes

Some quotes from users of Snowflake

Open Source Mag: Learn best of React Native with these open source projects: http://opensourceforu.com/2016/05/learn-best-of-react-native-with-these-open-source-projects/

ICICletech Blog: Mobile App Development With 8 Awesome React-Native Starter Kits: We have listed some of our favorite starter kits and boilerplates to get started quickly. https://www.icicletech.com/blog/react-native-starter-kits

Infinite.Red: Ignite Your Mobile Development:

awesome releases as Barton Hammond’s snowflake.

https://shift.infinite.red/ignite-your-mobile-development-32417590ed3e#.pz7u3djtm

AdtMag: New Community Projects for React Native: Deco IDE and Pepperoni Boilerplate https://adtmag.com/articles/2016/05/26/react-native-projects.aspx Snowflake mentioned

Pepperoni App Kit (see Credits)

This project was initially motivated by Snowflake....you should check it out to see if it's a good fit for your app.

Viktor

Just saw the tweets, still watching the vids. It's awesome!! It's really really high quality, I'm truly amazed

John

project is awesome, thank you for providing it!

Eric:

I've been going through snowflake and love what you have done!

Nikos:

wow new videos, nice

Josh

thanks for the thorough videos!

Patrick

just wanna snowflake is awesome

Justin

Congrats - the project is super helpful

Stephen

Thanks so much for this amazing foundation!

Jim

Neat project


Technologies

The following are brief descriptions of the technologies used

React-Native

React Native enables you to build world-class application experiences on native platforms using a consistent developer experience based on JavaScript and React.

What more can I say? It's a fantastic leap forward in providing the ability to write native applications with Javascript that target both iOS and Android.

This application provides one code base that works on both platforms. It demonstrates Form interactions, Navigation, and use of many other components.

Jest

85 Unit tests that cover plain objects and JSX components

The de-facto standard for React/Native testing. This app demonstrates how to mock ReactNative, node_modules, classes and to properly test JSX components by programmatically changing the props, and throughly test the applications data state and the actions in conjunction with Redux.

Jest Coverage Analysis

Redux

Redux is a predictable state container for JavaScript apps. It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test.

Before Redux, application state was managed by all the various components in the app. Now, the state is managed in a predictable and consistent manner and it can be tested with Jest and best of all, it is independent of the UI. This is a major advancement in application design!

Hapi

For me, Hapi provided a clear way for defining APIs and managing things clearly. Some folks like Express, I've used Express myself, and I wanted to try Hapi. I'm very satisfied with Hapi. As you may or may not know, WalMart Labs produced Hapi and they've used it in their business.

One of the needs of any application is server side processing. With the ability to run Hapi locally or on OpenShift, I'm able to write my server logic and test it locally. When I'm "happy" I can push the code to OpenShift. The same code runs in both environments.

Parse Server

As an alternative to Hapi, Snowflake also supports Parse Server. Parse Server is an open source version of the Parse backend that can be deployed to any infrastructure that can run Node.js.

Parse Server works with the Express web application framework. You can test it locally and push changes to your parse remote server when you are ready.

OpenShift

I chose OpenShift because I could get a reasonable performing application for free. The Snowflake server (https://github.com/bartonhammond/snowflake-hapi-openshift uses 3 gears with MongoDB and Redis.

TComb

A structured model based approach to declarative forms

*With this library, you simplify form processing incredibly! Write a lot less code, get usability and accessibility for free (automatic labels, inline validation, etc) and no need to update forms when domain model changes. This application demonstrates how to test these forms also!

Validate.js

Validate.js provides a declarative way of validating javascript objects.

Using Validate.js for the Form processing was a breeze! And with the ability to test the validations to the Redux state was very easy!


Continuous Integration

CI proves to the developer that everything required to build and test the application is well defined and repeatable. Without CI, one would not know, for a fact, that all the required tools and assests are available for everyone to build with. CI gives us developers some "peace of mind" that our build process is repeatable.

The following videos will walk you through setting up CI with BitRise.io


Introduction
Introduction
  • Snowflake is a starter app so all tutorials are basic in nature
  • There are a bizzilion ways of doing any of this - I'm showing one
  • There's a number of CI sites, I chose Bitrise.io
  • There's a general understanding of why to us a CI
  • The build will be done on Bitrise.io - not locally
  • The only goal is to get the build to run on Bitrise.io
  • You can still run applications locally with simulators
Bitrise Overview
Bitrise.io Overview
  • Introduction to Bitrise.io https://www.bitrise.io/
  • Overview of what it does for us
  • Overview of the two WorkFlows
    • iOS
    • Android
iOS XCode Modifications
iOS XCode Modifications
XCode Certs Provision Profiles App Id
XCode Certs Provision Profiles
Create iOS App
Create iOS App
  • Login/Register Bitrise.io
  • Dashboard
  • Add App
  • Authenticate GitHub
  • Select repository, branch
  • Import YML
  • Download Certifications
  • Update KeyChain
  • Save .p12
  • Download Provision
  • Load .p12 and provision to Bitrise.io
  • Setup Secret and Env Vars
  • Build
iOS install
iOS install from email
  • From device, open email app
  • Open letsconnect
  • Follow instructions to load in Safarie
  • Follow prompts and enjoy!
Android Setup
Android Setup
  • Settings -> Docker Image
  • Secret Variables
  • App/build.gradle
  • Setup Secret and Env Vars
  • Import YML
  • Run build
Addendum #1
XCode Edge Stack
  • "XCode Edge Stack" for iOS
  • New React-Native steps for Install & Bundle
  • Upgraded Step versions
  • GitHub branch triggers
Things not addressed
  • Submission to any store
  • Working with other CIs
  • Complex setups for either iOS or Android
  • Debugging any failures
  • Shiny new things
  • No local builds with Bitrise CLI
  • No local builds with Fastlane
  • No tutorial on all the features of Fastlane

Redux State Management

This section explains a little about what I've learned with Redux and the management of application state.

Without Redux

Alt text

custom_mark10 digraph G { aize ="4,4"; login [shape=box]; login -> validate [style=bold,label="1"]; login -> restful [style=bold,label="2"]; restful -> parse [style=bold,label="3"]; login -> router [style=bold,label="4"]; router-> new_page [style=bold,label="5"]; } custom_mark10

A typical app, at least those I've written before, have logic and state scattered all through out. Frameworks help to organize but typically the developer has to know how to "stitch" it together by remembering to update certain state at certain times.

In the above diagram, the Login component is responsible for calling the Validate and making sure the rules are applied and errors are displayed. Then it has to have logic that confirms everything is in the right state, and pass that data to a Restul API to interact, in this case, with Parse. When that activity is complete the Router has to be informed and a new_page can be displayed.

This makes testing hard as the logic is partially contained in the Login component itself and the sequence of those events are encapsulated there too!

With Redux

Alt text

custom_mark11 digraph G { aize ="4,4"; login [shape=box]; login -> Action[style=bold,label="1"]; Action -> Reducer [style=bold,label="2"]; Reducer -> login [style=bold,label="3"]; login -> Action [style=bold,label="4"]; Action -> restful [style=bold,label="5"]; restful -> parse [style=bold,label="6"]; Action -> Reducer [style=bold,label="7"]; Reducer -> new_page [style=bold,label="8"]; } custom_mark11

What the above diagram depicts is that the logic for login is contained in the Actions and Reducer and can be tested in isolation from the UI. This also makes the UI Component Login much simpler to write as it just renders content based on props that are provided. The props are actually the Reducer Store.

So what is happening in this diagram? Where's the Validation? That would be in step 1. When the user enters characters on the form, they are sent to an action. The action packages them up and sends them to the Reducer. The reducer looks at what Type the Action is and performs the operation, in this case, Validate the parameters.

How does Login respond? Well, it recieves the updated Props - the properties which are the store. It then renders it's output based on those properties. Just straight forward logic - nothing more then checking the properties and display approptiately. At no time does the Login component change any property state.

The responsibility of changing state belongs to the Reducer.

Every time an Action is called, that Action interacts w/ the Reducer. The Reducer does state changes on the State or Store model.

Let's look at a concrete example, Resetting a Password. Now the UI is pretty simple, provide a Text Input for the email entry and a Button to click. Let's further assume that the email has been validated and the user clicks the "Reset Password" button. All that Login does is call an Action function called resetPassword passing the email value.

So don't get too overwhelmed with the following code. You can think of the dispatch calls as meerly as a messaging system. Each dispatch call invokes a function - it just calls a function in a Promise chain.

I want to now look at one specific Action and trace it's path. That action is the dispatch(resetPasswordRequest()); call. That call signals that the "reset password request" processing is starting. We'll look at that next and how it trickles all the way back to the Login ui.

Action.resetPassword

export function resetPassword(email) {
  return dispatch => {
    dispatch(resetPasswordRequest());
    return new Parse().resetPassword({
      email: email
    })
      .then((response) => {
        if (response.status === 200 || response.status === 201) {
          dispatch(loginState());
          dispatch(resetPasswordSuccess());
        } else {
          dispatch(resetPasswordFailure(JSON.parse(response._bodyInit)));
        }
        return response;
      })
      .then((response) => {
        if (response.status === 200 || response.status === 201) {
          dispatch(emitLoggedOut());
        }
      })
      .catch((error) => {
        dispatch(resetPasswordFailure(error));
      });

  };
}

The simple function returns an object with type RESET_PASSWORD_REQUEST. All of the activities performed have this pattern, make a REQUEST and then either have a SUCCESS or a FAILURE.

Now Redux is responsible for taking this returned Action object and passing it to the Reducer. What does the Reducer do with this Action? We'll look at that next.

Action.resetPasswordRequest

export function resetPasswordRequest() {
  return {
    type: RESET_PASSWORD_REQUEST
  };
}

The Reducer is a function with 2 parameters, state and action. What it does is to make modifications to the state depending upon the action. The state is any javascript object you like. This application uses Immutable.js for it's state so to guarantee the state is always immutable.

Notice the switch statement - it's looking at that Action.type value - all Actions have a type value. In our case, the type is RESET_PASSWORD_REQUEST.

So what's happening here. If any request type comes to the Reducer, including RESET_PASSWORD_REQUEST, we change the state by setting the form.isFetching to true and the form.error field to null. The returned new state value has these two fields set.

What happens with that new state? Well Redux makes that state available in the Login component props. And since the props have changed, Login needs to render. Let's look at that next.

Reducer.Action.ResetPasswordRequest snippet

export default function authReducer(state = initialState, action) {
  if (!(state instanceof InitialState)) return initialState.mergeDeep(state);
  switch (action.type) {

  case SESSION_TOKEN_REQUEST:
  case SIGNUP_REQUEST:
  case LOGOUT_REQUEST:
  case LOGIN_REQUEST:
  case RESET_PASSWORD_REQUEST:
      let nextState =  state.setIn(['form', 'isFetching'], true)
        .setIn(['form','error'],null);
    return nextState;
.....

So here in the render component we need to decide if a spinner should be displayed. It should display when the props.isFetching is true. That's the value set above in the Reducer! All the Login render() has to do is check that property and set the UI appropriately.

Login.Header.render snippet

  render() {
    let spinner = <Text> </Text>;
    if (this.props.isFetching) {
      spinner =  <GiftedSpinner/>;
    }

    return (
      <View style={styles.header}>
        <Image style={styles.mark} source={{uri:
                                            'http://i.imgur.com/da4G0Io.png'}}
        />
        {spinner}
      </View>
    );
  }

Hopefully this gives you some insight into how Redux is integrated into the application. In my opinion, this is a huge step in application logic.

If you'd like to read an excellent tutorial on Redux I can't recommend this one enough: http://teropa.info/blog/2015/09/10/full-stack-redux-tutorial.html


Hot Reloading

This video shows Snowflake exporting and importing state from Redux. It demonstrates, with the iOS Simulator, the process of copying the state for import at a later time. After the demo, I walk through the code to clarify how I achieved this. It's assumed you have some familiarity with Redux. Hopefully it helps you gain a better understanding of what Redux provides you!

Snowflake Hot Loading


Faq

How do I change the Language of the App?

Just use the Settings of your Device or Simulator.

Why did you use the RestAPI instead of the (JS-sdk | ParseReact)

I looked at it initially and, imo, it had too much magic. For example, I couldn't see how I was going to isolate my JSX components easily and keep all my "state" in Redux. ParseReact is right there in the middle of your JSX component which would tie me to a very particular vendor and implementation detail. If I decided to later move away from ParseReact I'd have to rewrite a lot of code and tests.

Also, it had this statement

Mutations are dispatched in the manner of Flux Actions, allowing updates to be synchronized between many different components without requiring views to talk to each other

I don't want to deal w/ wrapping my head around Flux Actions and have to monkey-patch or something to get Redux Actions.

In a previous life, I worked with Parse JS SDK and it's based on backbone.js. So I didn't go that direction either, because, again, I didn't want to have another data model to deal with. Plus, at the time I was using it, the SDK was buggy and it was difficult to work with.

With the Parse Rest API, it's simple, can be tested itself from the command line with curl, it's clear, it's succinct and it's easily replaced with something else, an example such as Mongo/Mongoose without much, if any, impact on the code base.

-barton hammond

NPM DownloadsLast 30 Days