React Native – 7 Effective Patterns To Improve Development Experience

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn about the React Native 7 effective simple patterns which helps to improve our react native experience during development mode. We will discuss about react native 7 effective simple patterns one by one.

  • Keep most of components stupid
  • Rely on callbacks
  • Keep navigation stack away from views
  • Keep callbacks chained together
  • Keep reducers simple and declarative
  • Keep business logic out of Reducers
  • Keep platform-specific components to a minimum

A famous quote about Learning is :

Tell me and I forget, teach me and I may remember, involve me and I learn.

So Let’s begin.


Pattern 1 : Keep most of components stupid

  • This is true for any React application. Our views and components should rely on props and callbacks while Container (smart) components should rely on state.
  • We recommend using Redux, but in some applications we can get away using plain old setState. MobX is a great alternative too.


Pattern 2 : Rely on callbacks

  • When we learn how to code iOS apps in Swift, we taught to use the delegate pattern to decouple a view from its behavior. In React Native, the same effect can be achieved via callbacks.
  • Callbacks are simply Arrow Functions which can be passed to a component. The component has the responsibility to execute them, but doesn’t need to know what it’s actually doing.
  • Most component should not have any behavior. Expose simple callbacks, they are like the public API of our components. We should know when they’ll be executed by reading their names. If we are developing an e-commerce app, for example, names like onSelectProduct or onProductAddedToShoppingCart are very declarative.
  • When deciding whether to expose a callback or not, every time a component has some kind of user interaction, ask ourself this:
    Is this interaction only important for this particular component, or can it trigger changes in another part of the application? ” If the latter is our answer, then we should expose a callback.


Pattern 3 : Keep navigation stack away from views

  • For this particular application, we were able to migrate from React Native’s default Navigator, to NavigationExperimental, to React Navigation. Those changes involved a few lines of code.
  • The idea is simple: Screens and Views are not the same. Our views should not have any knowledge of the Navigation Stack while Screens (or Routes, depending on what name we prefer) must know how to navigate and how to communicate with the Navigation Bar / TabBar. With this approach, our screens will simply wrap the actual Views with navigation-aware things, For example:
const FavoritesView = ({ favorites, onSelectFavorite }) =>    

const FavoritesScreen = ({ navigation }) =>
   navigation.push('FAVORITE', {{ favorite: favorite }})}/>

const NavigationStack = StackNavigator({
  FAVORITES: FavoritesScreen,
  FAVORITE: FavoriteScreen
})
  • As we can see, FavoritesView simply exposes an ‘onSelectFavorite’ callback and doesn’t care about what it actually does. FavoritesScreen uses that callback to tell the navigator to navigate to another screen. Therefore, this gives us the flexibility to replace the way our navigation stack works and provides a nice separation.


Pattern 4 : Keep callbacks chained together

  • A very common pattern is to inject behavior into callbacks within Higher order Components (that’s what Redux’s mapStateToProps actually does), but many people forget that a public callback may be used in another part of the app (an outer component, for example).
  • Every time one of our views exposes a callback which may be used in another part of our application (such as, mapStateToProps), first invoke the actual callback passed on props. This enables us to, for example, Navigate to a screen and also fetch some information to feed the next view.
const mapDispatchToProps = (dispatch, props) => ({
   onSelectFavorite: (favorite) => {
     props.onSelectFavorite(favorite);
     dispatch(fetchFavoriteInfo(favorite.id));
   }
})

const mapStateToProps = (state) => ({
   favorites: state.favorites
})

export default connect(mapStateToProps, mapDispatchToProps)(FavoritesView)
  • Following the previous example, if FavoritesScreen told FavoritesView to navigate to the FavoriteScreen when selecting a Favorite, Redux would honor that, but also invoke some Redux actions.
  • As we may see, every realm knows how to handle its stuff: Screens know how to navigate, Connected Views know how to handle redux actions and Views are dumb, stateless and rely on their props.


Pattern 5 : Keep reducers simple and declarative

  • Any developer should be able to view your reducer’s code and understand what it’s doing. In most cases, having one function per action type can increase readability. For example:
const clear = (favoriteId) => state => ...
const fetching = (favoriteId) => state => ...
const finishFetching = (favoriteId, favorite) => state => ...

export default (state = {}, action) => {
    switch (action.type) {
        case 'CLEAR_FAVORITE':
            return clear(action.favoriteId)(state);
        case 'FETCHING_FAVORITE':
            return fetching(action.favoriteId)(state);
        case 'FINISH_FETCHING_FAVORITE':
            return finishFetching(action.favoriteId, action.favorite)(state);
        default:
            return state;
    }
}
  • Composing reducer functions with many one-line functions can give us greater flexibility and code reuse.


Pattern 6 : Keep business logic out of Reducers

  • Redux store is not part of business model, it’s a View Model. Treat it like such. Reducer should only impact the store with changes, and we need to be highly confident of them. The less knowledge Reducers have of own business rules, the simpler they’ll become.
  • It’s not the best approach, but a better one to put business logic in action creators, specially if we use a middleware like Thunk. Sagas and Epics are great too.


Pattern 7 : Keep platform-specific components to a minimum

  • Every platform has its own Design/UX language and in many cases we have to write different versions of a component. Remember that React Native’s aim is learn once, write anywhere, but first try not to rush into writing platform-specific components.
  • In many cases, simple Style-changes and conditional operators are enough. we’ve created a simple helper function called platformSpecific which allows me to set styles according to a platform.It’s a really simple function, but incredibly useful. For example :
const platformSpecific = ({ios, android}) => (Platform.OS == ‘ios’) ? ios : android

That’s all about in this article.


Conclusion

In this article, We understood the React Native 7 effective simple patterns with the below summary :

  • Keep most of the components simple and dumb
  • Expose callback
  • Keep navigation stack separate from views
  • Keep callbacks chained together
  • Reducer code should be simple and declarative form
  • Application business logic should be separated from Reducer
  • Platform specific components should be used minimum. Use common components code for different platforms if possible.

Thanks for reading ! I hope you enjoyed and learned about the React Native 7 effective simple patterns. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

Loading

Leave a Comment