Thursday, January 17, 2019

React Native : Anatomy of React - Redux Connect

React provides two major mechanisms for providing data to components namely: props and state. While props are read-only and allow a parent component to pass attributes to a child component, state is local and encapsulated within the component and can change at any time in the component’s lifecycle.

Since state is a very powerful mechanism for building powerful and dynamic React apps, it becomes necessary that state is properly managed in the application. Several libraries already exist, that provide a well-structured architecture for managing application state such as Flux, Redux, MobX.

Redux is a predictable state container for JavaScript apps ranging from vanilla apps to framework apps. It has a very tiny footprint and yet allows you to write consistent apps that can run in any environment:

The react-redux package provides React bindings for the Redux state container making it very easy for a React application to be connected to a Redux store.

    Presentational Components — These components are only concerned with how things look and are not aware of the Redux state. They get their data from props and may trigger callbacks passed to them via props.
    Container Components — These components are responsible for how things work and are fully aware of the Redux state. They are often created using React Redux and may dispatch Redux actions. They also subscribe to changes in the Redux state.

The react-redux package exposes a very simple interface, and all you should be interested in is just the following:

     — Wraps the React application and makes the Redux state available to all container components in the application’s hierarchy
    connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]) — Creates a higher-order component for making container components out of base React components

the react-redux connect() API is used for creating container elements that are connected to the Redux store. The Redux store to be connected to is derived from the topmost ancestor of the component using the React context mechanism. You have no need for connect() if you are only creating a presentational component.

Whether you want to just get data from the Redux store, or you want to dispatch actions on the Redux store, or you want to do both in your React component, you can make the component a container component by wrapping it in a higher-order component returned by react-redux connect()



References:
https://blog.logrocket.com/react-redux-connect-when-and-how-to-use-it-f2a1edab2013

React Native: What is reducer


The reducer is a pure function that takes the previous state and an action, and returns the next state. (previousState, action) => newState. It's called a reducer because it's the type of function you would pass to Array.prototype.reduce(reducer, ?initialValue) .

Reducers specify how the application's state changes in response to actions sent to the store. Remember that actions only describe what happened, but don't describe how the application's state changes.

Designing the State Shape

In Redux, all the application state is stored as a single object. It's a good idea to think of its shape before writing any code. What's the minimal representation of your app's state as an object?

For our todo app, we want to store two different things:

    The currently selected visibility filter.
    The actual list of todos.

You'll often find that you need to store some data, as well as some UI state, in the state tree. This is fine, but try to keep the data separate from the UI state.

{
  visibilityFilter: 'SHOW_ALL',
  todos: [
    {
      text: 'Consider using Redux',
      completed: true
    },
    {
      text: 'Keep all state in a single tree',
      completed: false
    }
  ]
}


Handling Actions

Now that we've decided what our state object looks like, we're ready to write a reducer for it. The reducer is a pure function that takes the previous state and an action, and returns the next state.


It's called a reducer because it's the type of function you would pass to Array.prototype.reduce(reducer, ?initialValue). It's very important that the reducer stays pure. Things you should never do inside a reducer:

    Mutate its arguments;
    Perform side effects like API calls and routing transitions;
    Call non-pure functions, e.g. Date.now() or Math.random().


We'll start by specifying the initial state. Redux will call our reducer with an undefined state for the first time. This is our chance to return the initial state of our app:

Below is an example where more actions are handled

import {
  ADD_TODO,
  TOGGLE_TODO,
  SET_VISIBILITY_FILTER,
  VisibilityFilters
} from './actions'

...

function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    case ADD_TODO:
      return Object.assign({}, state, {
        todos: [
          ...state.todos,
          {
            text: action.text,
            completed: false
          }
        ]
      })
    default:
      return state
  }
}

we never write directly to state or its fields, and instead we return new objects. The new todos is equal to the old todos concatenated with a single new item at the end. The fresh todo was constructed using the data from the action.

References:
https://redux.js.org/basics/reducers

React Native - Data Storage options

Quick and dirty: just use Redux + react-redux + redux-persist + AsyncStorage for react-native.
It fits almost perfectly the react native world and works like a charm for both android and ios. Also, there is a solid community around it, and plenty of information.

With react native, you probably want to use redux and redux-persist. It can use multiple storage engines. AsyncStorage and redux-persist-filesystem-storage are the options for RN.

Using redux + redux-persist you can define what is persisted and what is not. When not persisted, data exists while the app is running. When persisted, the data persists between app executions (close, open, restart phone, etc).

AsyncStorage has a default limit of 6MB on Android. It is possible to configure a larger limit (on Java code) or use redux-persist-filesystem-storage as storage engine for Android.

Using redux + redux-persist + AsyncStorage the setup is exactly the same on android and iOS.

Using redux, offiline access is almost automatic thanks to its design parts (action creators and reducers).

All data you fetched and stored are available, you can easily store extra data to indicate the state (fetching, success, error) and the time it was fetched. Normally, requesting a fetch does not invalidate older data and your components just update when new data is received.

The same apply in the other direction. You can store data you are sending to server and that are still pending and handle it accordingly.

React promotes a reactive way of creating apps and Redux fits very well on it. You should try it before just using an option you would use in your regular Android or iOS app. Also, you will find much more docs and help for those.



References:
https://stackoverflow.com/questions/44376002/what-are-my-options-for-storing-data-when-using-react-native-ios-and-android

Create Native App Tool



Its a new tool that makes it significantly easier to get started with a React Native project!

With Create React Native App, there’s no need to use Xcode or Android Studio, and you can develop for your iOS device using Linux or Windows.
This is accomplished using the Expo app, which loads and runs CRNA projects written in pure JavaScript without compiling any native code.

$ npm i -g create-react-native-app
$ create-react-native-app my-project
$ cd my-project
$ npm start

This will start the React Native packager and print a QR code. Open it in the Expo app to load your JavaScript. Calls to console.log are forwarded to your terminal. You can make use of any standard React Native APIs as well as the Expo SDK.

Native code with Create React Native

Many React Native projects have Java or Objective-C/Swift dependencies that need to be compiled. The Expo app does include APIs for camera, video, contacts, and more, and bundles popular libraries like Airbnb’s react-native-maps, or Facebook authentication. However if you need a native code dependency that Expo doesn’t bundle then you’ll probably need to have your own build configuration for it. Just like Create React App, “ejecting” is supported by CRNA.

You can run npm run eject to get a project very similar to what react-native init would generate. At that point you’ll need Xcode and/or Android Studio just as you would if you started with react-native init , adding libraries with react-native link will work, and you’ll have full control over the native code compilation process.

Now with the above theory. Tried to create the project actually and below was the results

It asked whether require Expo CLI.
This command requires Expo CLI.
Do you want to install it globally [Y/n]? Y



References:
https://facebook.github.io/react-native/blog/2017/03/13/introducing-create-react-native-app

What is difference between CRNA and Expo?

create-react-native-app is the quickest way to start a new React Native project. It uses the Expo client and some of the Expo devtools but not all of them. For example, you don't need to create an Expo developer account to use CRNA and we've found it's faster to get started with CRNA than with XDE (the Expo development app).

Since CRNA projects run in the Expo client, you do have access to most of the Expo APIs such as native maps, audio, OpenGL, and more. There are a couple of exceptions like push notifications that only Expo projects can use, but there are many more similarities than differences between CRNA projects and Expo projects.

CRNA was also designed to give you several paths forward as your app grows. The three paths are:

    Use Expo: You actually can open a CRNA project with the Expo XDE app if you want all the features of Expo including push notifications and IPA / APK files for the App Store / Play Store.
    Eject to ExpoKit: ExpoKit is a native library that includes React Native and the Expo APIs. This path creates Xcode and Android Studio projects with ExpoKit so that most Expo APIs keep working if you were using them before. You then build IPA / APK files the way you would as any other native app.
    Eject to bare React Native: This path gives you a plain React Native project with separate Xcode and Android Studio projects. All modules that come with React Native will work but Expo APIs won't work (use ExpoKit above for that) because this is bare React Native.

Note that when you eject, CRNA won't manage upgrades for you so you're responsible for upgrading React Native.


References
https://github.com/react-community/create-react-native-app/issues/153

What is ssh-add?

ssh-add is a command for adding SSH private keys into the SSH authentication agent for implementing single sign-on with SSH. The agent process is called ssh-agent; see that page to see how to run it.

The cool thing about ssh-agent and ssh-add is that they allow the user to use any number of servers, spread across any number of organizations, without having to type in a password every time when moving between servers. This is commonly used by system administrators to move among the machine they administer. It is also widely used in universities and research institutions for accessing computing resources. However, it has also lead to proliferation of SSH keys in enterprises, and that is something administrators should be aware of and audit should take steps to address.

References:
https://www.ssh.com/ssh/add

iOS : Visual format language

Below are the essential syntax elements for visual layout

[button]-[textField] => Specifies standard spacing between button and textfield
[button(>=50)] => Specifies the minimum width of 50.
|-50-[purpleBox]-50-| => Specifies connection to super view, | indicates super view
V:[topField]-10-[bottomField] => Specifies vertical layout, spacing between top and bottom field being 10px.
[maroonView][blueView] => Flushing views, this means no spacing with the adjacent views. 
[button(100@20)] => This tells that the priority is 20 for the button to have width as 100
[button1(==button2)] => Equal widths for buttons button1 and button2
[flexibleButton(>=70,<=100)] => This is a multiple predicate scenario, where the width lies between 70 and 100px
|-[find]-[findNext]-[findField(>=20)]-| => This declares find and find next and find field is having standard spacing horizontally. Find and FindField is having spacing with the border of 20px. FindField is having width of at least 20px.

References:
https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/VisualFormatLanguage.html#//apple_ref/doc/uid/TP40010853-CH27-SW1