Android – How To Compare Valuable Constraint Layout With Relative Layout ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, We will learn about Android Layouts Constraint Layout and Relative Layout differences. The differences between Constraint Layout and Relative Layout is the most common question asked in an interview with the experience android developer. This article will demonstrate the differences based on hierarchy, GUI builder and recomputing size and position of Constraint Layout rather than Relative Layout.

A famous quote about Learning is :

” The beautiful thing about learning is that nobody can take it away from you.”

So, Let’s begin.

Overview

By the definition of Constraint Layout,

” Constraint Layout is a view group that allows you to create large and complex layouts with a flat view hierarchy (no nested view groups). It’s similar to Relative Layout  in that all views are laid out according to relationships between sibling views and the parent layout, but it’s more flexible than RelativeLayout and easier to use with Android Studio’s Layout Editor.

and the definition of Relative Layout,

“Relative Layout is a view group that displays child views in relative positions. The position of each view can be specified as relative to sibling elements (such as to the left of or below another view) or in positions relative to the parent Relative Layout area (such as aligned to the bottom, left or center).”

We try to understand the differences between layouts with below diagrams :

In the diagram, Constraint layout has one layout means flat hierarchy, but Relative layout has nested layouts.

Nice !!

We can discuss the differences between Layouts as brief with the below points :


1. Flat View Hierarchy – No nested view groups

Constraint Layout has flat view hierarchy unlike other layouts, so it does a better performance than Relative Layout. It is the biggest advantage of constraint Layout, the only single layout can handle your UI. Where in the Relative layout, you need multiple nested layouts means (LinearLayout+RelativeLayout).


2. GUI Builder – Drag and drop functionality

In Android Studio you can drag and drop GUI component like TextView , Button , TextInputLayout etc. So now its make life easier to developers and make they work faster UI development and more productive so they continue improving drag-drop GUI builder. However drag-and-drop gestures, the developer is only providing you with X/Y coordinates of a widget, based on where you release the mouse button and completes the drop.

With RelativeLayout is difficult for GUI builder to handle drag-drop and probably you will have to dig inside the XML code to get things done.

But in ConstraintLayout, you have an option to constraint applying by the use of blueprint and visual editor tool which makes it easy to design a page.


3. Recomputing size and position

Each changes the detail of a widget often cause the sizes to have to be recomputed. 

Let’s take an example a change in EditText might starting point that a whole hierarchy to go through re-size and re-position work. If the application UI (user interface) has a container inside the container which is inside another container etc. Means that parents re-size or re-position their children and that can be very expensive (rework again on the user interface) for deep hierarchies.

So understanding the differences between the layouts, we can ask some questions related to layouts.


1. Does the ConstraintLayout have better performance than a nested Layout?

Yes, ConstraintLayout has designed with performance optimization in mind, more effective, easy use and trying to eliminate as many pass scenarios as possible. This is done by eliminating the deeply-nested view hierarchies with flat view hierarchy.


2. Can we replace RelativeLayout with ConstraintLayout completely?

Yes, you can completely replace RelativeLayout with ConstraintLayout.ConstraintLayout does all that RelativeLayout does, and more.


Conclusion

In this article, We understood the difference between Constraint Layout and Relative Layout in Android.  We conclude that

  • Constraint layout follows flat view hierarchy, but Relative layout has nested layouts.
  • This layout has an option to constraint applying by using blueprint and visual editor tool to design a page easily, but Relative layout is difficult for GUI builder to handle drag-drop and look up XML code to get things done.
  • Constraint layout uses flat view hierarchy so parent re-size or re-position their children can do easily, but Relative Layout can difficult and very expensive (rework again on the UI) for deep hierarchies.

Thanks for reading ! I hope you enjoyed and learned about Android Layouts Constraint Layout and Relative Layout differences. 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 !!???

JavaScript – 7 Quick Valuable Core Concepts Of Functional Programming

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn about the functional programming core concepts in JavaScript which helps to improve your functional code tends to be more concise, more predictable, and easier to test. Functional programming has become a really hot topic in the JavaScript World.

A famous quote about learning is :

Try to learn something about everything and everything about something.


So Let’s begin.


What is Functional Programming ?

Functional Programming is :

  • The process of building software by composing pure functions, avoiding shared statemutable data, and side-effects
  • Declarative rather than imperative, and application state flows through pure functions.
  • A programming paradigm, meaning that it is a way of thinking about software construction based on some fundamental, defining principles.

In Contrast with object oriented programming, where application state is usually shared and colocated with methods in objects.

Other examples of programming paradigms include object oriented programming and procedural programming.

We can say that in functional programming, functional code tends to be more concise, more predictable, and easier to test than imperative or object oriented code.

After that, Second question is in our mind that :


Why is it most important in the JavaScript World ?

To understand the meaning and importance of the functional programming, we need to understand the below core concepts:

  • Pure functions
  • Function composition
  • Avoid shared state
  • Avoid mutating state
  • Avoid side effects
  • Reusability through Higher Order Functions
  • Declarative vs Imperative


1. Pure function :

A pure function is a function which :

  • Given the same inputs, always returns the same output, and 
  • Has no side-effects

Pure functions have lots of properties that are important in functional programming, including referential transparency (You can replace a function call with its resulting value without changing the meaning of the program). 


2. Functional Composition :

Functional composition is the process of combining two or more functions in order to produce a new function or perform some computation. For example, the composition f.g (the dot means “composed with”) is equivalent to f(g(x)) in JavaScript. Understanding function composition is an important step towards understanding how software is constructed using  the functional programming.


3. Avoid Shared State :

Shared state is any variable, object, or memory space that exists in a shared scope, or as the property of an object being passed between scopes. A shared scope can include global scope or closure scopes.

Often, in object oriented programming, objects are shared between scopes by adding properties to other objects.

For example, a computer game might have a master game object, with characters and game items stored as properties owned by that objects. Functional programming avoids shared state  instead relying on immutable data structures and pure calculations to derive  new data from existing data.

Here question comes in our mind, that Why avoid the shared state ?

So there is two common problems with shared state :

  • The first problem with shared state is that in order to understand the effects of a function, you have to know the entire history of every shared variable that the function uses or affects.
  • Another common problem associated with shared state is that changing the order in which functions are called can cause a cascade of failures because functions which act on shared state are timing dependent.

When you avoid shared state, the timing and order of function calls don’t change the result of calling the function. With pure functions, given the same input, you’ll always get the same output. This makes function calls completely independent of other function calls, which can radically simplify changes and refactoring. A change in one function, or the timing of a function call won’t ripple out and break other parts of the program.


4. Avoid mutating state :

An immutable object is an object that can’t be modified after it’s created. Conversely, a mutable object is any object which can be modified after it’s created.

Immutability is a central concept of functional programming because without it, the data flow in your program is lossy. State history is abandoned, and strange bugs can creep into your software.

So here question comes in our mind, Why we talk about immutability or an immutable object ? but here topic heading is avoid mutating state.

So, to understand avoid mutating state concept, we need to first understand An immutable object or Immutability concept.

In JavaScript, it’s important not to confuse const, with immutability. const creates a variable name binding which can’t be reassigned after creation. const does not create immutable objects. You can’t change the object that the binding refers to, but you can still change the properties of the object, which means that bindings created with const are mutable, not immutable.

Immutable objects can’t be changed at all. You can make a value truly immutable by deep freezing the object. JavaScript has a method that freezes an object one-level deep.But frozen objects are only superficially immutable.

Then one more question comes in our mind, How to implement deep frozen for object and which mechanism or data structure is used?

In many functional programming languages, there are special immutable data structures called trie data structures (pronounced “tree”) which are effectively deep frozen — meaning that no property can change, regardless of the level of the property in the object hierarchy.

Tries use structural sharing to share reference memory locations for all the parts of the object which are unchanged after an object has been copied by an operator, which uses less memory, and enables significant performance improvements for some kinds of operations.

For example, you can use identity comparisons at the root of an object tree for comparisons. If the identity is the same, you don’t have to walk the whole tree checking for differences.

There are several libraries in JavaScript which take advantage of tries, including Immutable.js and more.


5. Avoid side effects :

A  side effect is any application state change that is observable outside the called function other than its return value. 

Side effects include : 

  • Modifying any external variable or object property (e.g., a global variable, or a variable in the parent function scope chain)
  • Logging to the console
  • Writing to the screen
  • Writing to a file
  • Writing to the network
  • Triggering any external process
  • Calling any other functions with side-effects

Side effects are mostly avoided in functional programming, which makes the effects of a program much easier to understand, and much easier to test. Haskell and other functional languages frequently isolate and encapsulate side effects from pure functions using  monads.

If you keep your side effects separate from the rest of your program logic, your software will be much easier to extend, refactor, debug, test, and maintain.

This is the reason that most front-end frameworks encourage users to manage state and component rendering in separate, loosely coupled modules.


6. Reusability through Higher Order Functions :

higher order function is any function which takes a function as an argument, returns a function, or both. Higher order functions are often used to :

  • Abstract or isolate actions, effects, or async flow control using callback functions, promises, monads, etc…
  • Create utilities which can act on a wide variety of data types
  • Partially apply a function to its arguments or create a curried function for the purpose of reuse or function composition
  • Take a list of functions and return some composition of those input functions

Functional programming tends to reuse a common set of functional utilities to process data. JavaScript has first class functions, which allows us to treat functions as data — assign them to variables, pass them to other functions, return them from functions, etc…


7. Declarative vs Imperative :

Functional programming is a declarative paradigm, meaning that the program logic is expressed without explicitly describing the flow control.

The two difference between Declarative and Imperative programs are :

  • Imperative programs spend lines of code describing the specific steps used to achieve the desired results — the flow control: How to do things. Where as Declarative programs abstract the flow control process, and instead spend lines of code describing the data flow: What to do. The how gets abstracted away.
  • Imperative code frequently utilizes statements. A statement is a piece of code which performs some action. Examples of commonly used statements include for, if, switch, throw, etc… where as Declarative code relies more on expressions. An expression is a piece of code which evaluates to some value. Expressions are usually some combination of function calls, values, and operators which are evaluated to produce the resulting value. 

That’s all about in this article.


Conclusion

In this article, We understood the functional programming core concepts in JavaScript. In Summary, Functional Programming favors :

  • Pure functions instead of shared state & side effects
  • Immutability over mutable data
  • Function composition over imperative flow control
  • Lots of generic, reusable utilities that use higher order functions to act on many data types instead of methods that only operate on their colocated data
  • Declarative rather than imperative code (what to do, rather than how to do it)
  • Expressions over statements
  • Containers & higher order functions over ad-hoc polymorphism

Thanks for reading ! I hope you enjoyed and learned about the functional programming core concepts in JavaScript. 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 !!???


iOS – Understanding KVO In Swift

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, We will learn about KVO in Swift. KVO, which stands for Key-Value Observing, is one of the techniques for observing the program state changes available in Objective-C and Swift. This article demonstrates the KVO importance in Objective-C and Swift with practical example.

A famous quote about learning is :

” One learns from books and example only that certain things can be done. Actual learning requires that you do those things.”

So Let’s begin.


Overview

The KVO concept is simple:

” When we have an object with some instance variables, KVO allows other objects to establish surveillance on changes for any of those instance variables. “

KVO is a practical example of the Observer pattern. What makes Objective-C (and Obj-C bridged Swift) unique is that every instance variable that you add to the class becomes observable through KVO right away!

But in the majority of other programming languages, such a tool doesn’t come out of the box – we usually need to write additional code in the variable’s setter to notify the observers about the value changes.

Swift has inherited KVO from Objective-C, so for a full picture we need to understand how KVO works in Objective-C.


KVO in Objective-C

Consider we have a class named Person with properties name and age

@interface Person: NSObject
 
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger age;
 
@end

The objects of this class now are able to communicate the changes of the properties through KVO, but with no additional code – this feature comes for free !

So the only thing we need to do is to start the observation in another class:

@implementation SomeOtherClass

- (void)observeChanges:(Person *)person {
    [person addObserver:self
             forKeyPath:@"age"
                options:NSKeyValueObservingOptionNew
                context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                       context:(void *)context {
    if ([keyPath isEqualToString:@"age"]) {
        NSNumber *ageNumber = change[NSKeyValueChangeNewKey];
        NSInteger age = [ageNumber integerValue];
        NSLog(@"New age is: %@", age);
    }
}

@end

That’s it! Now every time the age property changes on the Person we’ll have New age is: ... printed to the log from the observer’s side.

As we can see, there are two methods involved in KVO communication.

The first is addObserver:forKeyPath:options:context:, which can be called on any NSObject, including Person. This method attaches the observer to an object.

The second is observeValueForKeyPath:ofObject:change:context: which is another standard method in NSObject that we have to override in our observer’s class. This method is used for handling the observation notifications.

There is a third method, removeObserver:forKeyPath:context:, which allows us to stop the observation. It’s important to unsubscribe from notifications if the observed object outlives the observer. So the subscription just has to be removed in the observer’s dealloc method.

Now, let’s talk about the parameters of the methods used in KVO.

- (void)addObserver:(NSObject *)observer 
         forKeyPath:(NSString *)keyPath
            options:(NSKeyValueObservingOptions)options
            context:(nullable void *)context;

Here, The method have the following parameters:

  • observer is the object that will be receiving the change notifications. Usually, we provide self in this parameter, as the addObserver: is called from inside own instance method.
  • keyPath is a string parameter that in simplest case is just the name of the property we want to observe. If the property references a complex object hierarchy it can be a set of property names for digging into that hierarchy: "person.father.age"
  • options is an enum that allows for customizing what information is delivered with notification and when it should be sent. Available options are NSKeyValueObservingOptionNew and NSKeyValueObservingOptionOld, which control whether to include the most recent and the previous values respectively. There is also NSKeyValueObservingOptionInitial for triggering the notification right after the subscription, and NSKeyValueObservingOptionPrior for diffing the changes in a collection, such as insertions of deletions in NSArray.
  • context is a reference to object of an arbitrary class, which can be helpful for identifying the subscription in certain complex use cases, such as when working with CoreData. In most other cases we simply provide nil here.

The method we used for handling the update notifications

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                       context:(void *)context

Here, The method have the following parameters :

  • keyPath is the same string value we provided when attaching the observer. We may ask why it is provided here as well. The reason is that we may be observing multiple properties at once, so this parameter can be used to distinguish the notifications for one property from another.
  • object is the observed object. Since we can observe changes on more than one object, this parameter allows us to identify who’s property has changed.
  • change is the dictionary with information about the changed value. Based on the NSKeyValueObservingOptions we provided upon subscription, this dictionary may contain the current value under key NSKeyValueChangeNewKey, previous value for NSKeyValueChangeOldKey, and the “diff” information when observing changes in a collection: NSKeyValueChangeIndexesKey and NSKeyValueChangeKindKey
  • context is the reference provided upon subscription. Again, used for proper observation identification and in most cases can be ignored.


When KVO does not work

Even though KVO looks like magic, there is nothing extraordinary behind it. In fact, we can have direct access to its internals, which are hidden by default.

The trick is how Objective-C generates setter for properties. When we declare a property like

@property (nonatomic, assign) NSInteger age;

The factual setter generated by Objective-C is equivalent to the following:

- (void)setAge:(NSInteger)age {
    [self willChangeValueForKey:@"age"];
    _age = age;
    [self didChangeValueForKey:@"age"];
}

And if we explicitly define the setter without calling these willChangeValueForKey and didChangeValueForKey.

- (void)setAge:(NSInteger)age {
    _age = age;
}

… the KVO will stop working for this property.

So basically, these two methods willChangeValueForKey and didChangeValueForKey allow KVO to deliver the updates to the subscribers, and the developer can opt-out by omitting those calls from the setter.

It is important to understand that every @property synthesised by Objective-C adds a hidden instance variable with _ prefix.

For example, @property NSInteger age; generates an instance variable with the name _age that can be accessed just like the property:

self.age = 25;
self._age = 25;

The difference is that self.age = 25; triggers setter setAge:, while self._age = 25; changes the stored variable directly.

This means that even if the KVO is enabled for the age property, the KVO communication will work correctly for self.age = 25; and won’t deliver an update for self._age = 25;

Another way to break free from KVO is to not use @property in the first place, but instead store the instance variable in the anonymous category of the class:

@interface Person () {
    NSInteger _privateVariable;
}
@end

For such variables, Objective-C does not generate setter and getter, thus not enabling KVO.


KVO in Swift

Swift has inherited the support for the KVO from Objective-C, but unlike the latter, KVO is disabled in Swift classes by default.

Objective-C classes used in Swift keep KVO enabled, but for a Swift class we need to set the base class to NSObject plus add @objc dynamic attributes to the variables:

class Person: NSObject {
    @objc dynamic var age: Int
    @objc dynamic var name: String
}

There are two APIs available in Swift for Key-Value Observing: the old one, which came from Objective-C, and the new one, which is more flexible, safe and Swift-friendly.

Let’s start with the new one:

class PersonObserver {

    var kvoToken: NSKeyValueObservation?
    
    func observe(person: Person) {
        kvoToken = person.observe(\.age, options: .new) { (person, change) in
            guard let age = change.new else { return }
            print("New age is: \(age)")
        }
    }
    
    deinit {
        kvoToken?.invalidate()
    }
}

As we can see, the new API is using a closure callback for delivering the change notification right in the place where the subscription started.

This is more convenient and safe because we no longer need to check the keyPathobject or context, – no other notifications are delivered in that closure, just the one we’ve subscribed on.

There is a new way for managing the observation lifetime – the act of subscribing returns a token of type NSKeyValueObservation which has to be stored somewhere, for example, in an instance variable of the observer class.

Later on, we can call invalidate() on that token to stop the observation, like in the deinit method above.

The final change is related to the keyPath. String was error-prone because when we rename a variable the compiler won’t be able to tell us that the keyPath now leads to nowhere. Instead, this new API is using Swift’s special type for keyPath, which allows the compiler to verify the path is valid.

The options parameter has just the same set of options as in Objective-C. If we need to provide more than one option, we just bundle them in an array: options: [.new, .old]

The old API is also available, although it maintained all its disadvantages, so we encourage you to use the new API instead.

Here is the old one:

class PersonObserver: NSObject {
    
    func observe(person: Person) {
        person.addObserver(self, forKeyPath: "age",
                           options: .new, context: nil)
    }
    
    override func observeValue(forKeyPath keyPath: String?,
                               of object: Any?,
                               change: [NSKeyValueChangeKey : Any]?,
                               context: UnsafeMutableRawPointer?) {
        if keyPath == "age",
           let age = change?[.newKey] {
             print("New age is: \(age)")
        }
    }
}

The old API requires the observer to be an NSObject descendant as well. We also need to verify the keyPathobject, and context, since other notifications are also delivered in this method, just like in Objective-C.

That’s all about in this article.


Conclusion

In this article, We understood about KVO in Swift. This article described about the KVO importance in Objective-C and Swift with practical example.

Thanks for reading ! I hope you enjoyed and learned about the KVO Concepts in iOS. 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!!???

JavaScript – S.O.L.I.D – The Five Principles Of Object Oriented Design

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn about the Javascript 5 SOLID Principles. The SOLID principles are a set of software design principles, that help us to understand how we can structure our code in order to be robust, maintainable and flexible as much as possible.

“JavaScript is a loosely typed language, some consider it a functional language, others consider it an object oriented language, some think its both, and some think that having classes in JavaScript is just plain wrong. — Dor Tzur.”

From my experience, we’ll rarely want to use classes and long inheritance chains in JavaScript. But still, SOLID principles are pretty solid.

SOLID principles are the basic pillars of OOP set forward by our beloved Uncle Bob.

A famous quote about learning is :

” Live as if you were to die tomorrow. Learn as if you were to live forever. “

So Let’s begin.


What is S.O.L.I.D. ?

S.O.L.I.D. stands for :

  • S — Single responsibility principle
  • O — Open closed principle
  • L — Liskov substitution principle
  • I — Interface segregation principle
  • D — Dependency Inversion principle

Let’s see them one by one.


1. Single Responsibility Principle

“A class should have one and only one reason to change, meaning that a class should only have one job.”

For example, say we have some shapes and we wanted to sum all the areas of the shapes. 

const circle = (radius) => {
  const proto = { 
    type: 'Circle',
    //code 
  }
  return Object.assign(Object.create(proto), {radius})
}
const square = (length) => {
  const proto = { 
    type: 'Square',
    //code 
  }
  return Object.assign(Object.create(proto), {length})
}

First, we create our shapes factory functions and setup the required parameters.

so, What is a factory function ?

“In JavaScript, any function can return a new object. When it’s not a constructor function or class, it’s called a factory function.”

Next, we move on by creating the areaCalculator factory function and then write up our logic to sum up the area of all provided shapes.

const areaCalculator = (s) => {
  const proto = {
    sum() {
      // logic to sum
    },
    output () {
     return `
       <h1>
         Sum of the areas of provided shapes:
         ${this.sum()} 
       </h1>
    }
  }
  return Object.assign(Object.create(proto), {shapes: s})
}

To use the areaCalculator factory function, we simply call the function and pass in an array of shapes, and display the output at the bottom of the page.

const shapes = [
  circle(2),
  square(5),
  square(6)
]
const areas = areaCalculator(shapes)
console.log(areas.output())

The problem with the output method is that the areaCalculator handles the logic to output the data. Therefore, what if the user wanted to output the data as json or something else ?

All of the logic would be handled by the areaCalculator factory function, this is what ‘Single Responsibility principle’ frowns against; the areaCalculator factory function should only sum the areas of provided shapes, it should not care whether the user wants JSON or HTML.

So, to fix this you can create an SumCalculatorOutputter factory function and use this to handle whatever logic you need on how the sum areas of all provided shapes are displayed.

The sumCalculatorOutputter factory function would work liked this:

const shapes = [
  circle(2),
  square(5),
  square(6)
]
const areas  = areaCalculator(shapes)
const output = sumCalculatorOputter(areas)
console.log(output.JSON())
console.log(output.HAML())
console.log(output.HTML())
console.log(output.JADE())

Now, whatever logic you need to output the data to the users is now handled by the sumCalculatorOutputter factory function.


2. Open-Closed Principle

“Objects or entities should be open for extension, but closed for modification.”

Open for extension means that we should be able to add new features or components to the application without breaking existing code. Closed for modification means that we should not introduce breaking changes to existing functionality, because that would force you to refactor a lot of existing code — Eric Elliott”

In simpler words, means that a class or factory function in our case, should be easily extendable without modifying the class or function itself. Let’s look at the areaCalculator factory function, especially it’s sum method.

sum () {
 
 const area = []
 
 for (shape of this.shapes) {
  
  if (shape.type === 'Square') {
     area.push(Math.pow(shape.length, 2)
   } else if (shape.type === 'Circle') {
     area.push(Math.PI * Math.pow(shape.length, 2)
   }
 }
 return area.reduce((v, c) => c += v, 0)
}

If we wanted the sum method to be able to sum the areas of more shapes, we would have to add more if/else blocks and that goes against the open-closed principle.

A way we can make this sum method better is to remove the logic to calculate the area of each shape out of the sum method and attach it to the shape’s factory functions.

const square = (length) => {
  const proto = {
    type: 'Square',
    area () {
      return Math.pow(this.length, 2)
    }
  }
  return Object.assign(Object.create(proto), {length})
}

The same thing should be done for the circle factory function, an area method should be added. Now, to calculate the sum of any shape provided should be as simple as:

sum() {
 const area = []
 for (shape of this.shapes) {
   area.push(shape.area())
 }
 return area.reduce((v, c) => c += v, 0)
}

Now we can create another shape class and pass it in when calculating the sum without breaking our code. However, now another problem arises, how do we know that the object passed into the areaCalculator is actually a shape or if the shape has a method named area ?

Coding to an interface is an integral part of S.O.L.I.D., a quick example is we create an interface, that every shape implements.

Since JavaScript doesn’t have interfaces, So how can we achieved this, in the lack of interfaces ?

Function Composition to the rescue !

First we create shapeInterface factory function, as we are talking about interfaces, our shapeInterface will be as abstracted as an interface, using function composition.

const shapeInterface = (state) => ({
  type: 'shapeInterface',
  area: () => state.area(state)
})

Then we implement it to our square factory function.

const square = (length) => {
  const proto = {
    length,
    type : 'Square',
    area : (args) => Math.pow(args.length, 2)
  }
  const basics = shapeInterface(proto)
  const composite = Object.assign({}, basics)
  return Object.assign(Object.create(composite), {length})
}

And the result of calling the square factory function will be the next one:

const s = square(5)
console.log('OBJ\n', s)
console.log('PROTO\n', Object.getPrototypeOf(s))
s.area()

// output
OBJ
 { length: 5 }
PROTO
 { type: 'shapeInterface', area: [Function: area] }
25

In our areaCalculator sum method we can check if the shapes provided are actually types of shapeInterface, otherwise we throw an exception:

sum() {
  const area = []
  for (shape of this.shapes) {
    if (Object.getPrototypeOf(shape).type === 'shapeInterface') {
       area.push(shape.area())
     } else {
       throw new Error('this is not a shapeInterface object')
     }
   }
   return area.reduce((v, c) => c += v, 0)
}

and again, since JavaScript doesn’t have support for interfaces like typed languages the example above demonstrates how we can simulate it, but more than simulating interfaces, what we are doing is using closures and function composition.


3. Liskov Substitution Principle

“Let q(x) be a property provable about objects of x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.”

All this is stating is that every subclass/derived class should be substitutable for their base/parent class.

In other words, as simple as that, a subclass should override the parent class methods in a way that does not break functionality from a client’s point of view.

Still making use of our areaCalculator factory function, say we have a volumeCalculator factory function that extends the areaCalculator factory function, and in our case for extending an object without breaking changes in ES6 we do it by using Object.assign() and the Object.getPrototypeOf():

const volumeCalculator = (s) => {
  const proto = {
    type: 'volumeCalculator'
  }
  const areaCalProto = Object.getPrototypeOf(areaCalculator())
  const inherit = Object.assign({}, areaCalProto, proto)
  return Object.assign(Object.create(inherit), {shapes: s})
}

For Another example, if we want to implement classes for a bunch of shapes, we can have a parent Shape class, which are extended by all classes by implementing everything in the Shape class.

We can write the following to implement some shape classes and get the area of each instance:

class Shape {
  get area() {
    return 0;
  }
}
class Rectangle extends Shape {
  constructor(length, width) {
    super();
    this.length = length;
    this.width = width;
  }
  get area() {
    return this.length * this.width;
  }
}
class Square extends Shape {
  constructor(length) {
    super();
    this.length = length;
  }
  get area() {
    return this.length ** 2;
  }
}
class Circle extends Shape {
  constructor(radius) {
    super();
    this.radius = radius;
  }
  get area() {
    return Math.PI * (this.radius ** 2);
  }
}
const shapes = [
  new Rectangle(1, 2),
  new Square(1, 2),
  new Circle(2),
]
for (let s of shapes) {
  console.log(s.area);
}

Since we override the area getter in each class that extends Shape , we get the right area for each shape since the correct code is run for each shape to get the area.


4. Interface Segregation Principle

“A client should never be forced to implement an interface that it doesn’t use or clients shouldn’t be forced to depend on methods they do not use.”

Continuing with our shapes example, we know that we also have solid shapes, so since we would also want to calculate the volume of the shape, we can add another contract to the shapeInterface:

const shapeInterface = (state) => ({
  type: 'shapeInterface',
  area: () => state.area(state),
  volume: () => state.volume(state)
})

Any shape we create must implement the volume method, but we know that squares are flat shapes and that they do not have volumes, so this interface would force the square factory function to implement a method that it has no use of. 

Interface segregation principle says no to this, instead we could create another interface called solidShapeInterface that has the volume contract and solid shapes like cubes etc. can implement this interface.

const shapeInterface = (state) => ({
  type: 'shapeInterface',
  area: () => state.area(state)
})
const solidShapeInterface = (state) => ({
  type: 'solidShapeInterface',
  volume: () => state.volume(state)
})
const cubo = (length) => {
  const proto = {
    length,
    type   : 'Cubo',
    area   : (args) => Math.pow(args.length, 2),
    volume : (args) => Math.pow(args.length, 3)
  }
  const basics  = shapeInterface(proto)
  const complex = solidShapeInterface(proto)
  const composite = Object.assign({}, basics, complex)
  return Object.assign(Object.create(composite), {length})

This is a much better approach, but a pitfall to watch out for is when to calculate the sum for the shape, instead of using the shapeInterface or a solidShapeInterface.

We can create another interface, maybe manageShapeInterface, and implement it on both the flat and solid shapes, this is way we can easily see that it has a single API for managing the shapes, for example:

const manageShapeInterface = (fn) => ({
  type: 'manageShapeInterface',
  calculate: () => fn()
})
const circle = (radius) => {
  const proto = {
    radius,
    type: 'Circle',
    area: (args) => Math.PI * Math.pow(args.radius, 2)
  }
  const basics = shapeInterface(proto)
  const abstraccion = manageShapeInterface(() => basics.area())
  const composite = Object.assign({}, basics, abstraccion)
  return Object.assign(Object.create(composite), {radius})
}
const cubo = (length) => {
  const proto = {
    length,
    type   : 'Cubo',
    area   : (args) => Math.pow(args.length, 2),
    volume : (args) => Math.pow(args.length, 3)
  }
  const basics  = shapeInterface(proto)
  const complex = solidShapeInterface(proto)
  const abstraccion = manageShapeInterface(
    () => basics.area() + complex.volume()
  )
  const composite = Object.assign({}, basics, abstraccion)
  return Object.assign(Object.create(composite), {length})
}

As we can see until now, what we have been doing for interfaces in JavaScript are factory functions for function composition.

And here, with manageShapeInterface what we are doing is abstracting again the calculate function, what we doing here and in the other interfaces (if we can call it interfaces), we are using “high order functions” to achieve the abstractions.


5. Dependency Inversion Principle

“Entities must depend on abstractions not on concretions. It states that the high level module must not depend on the low level module, but they should depend on abstractions.”

As a dynamic language, JavaScript doesn’t require the use of abstractions to facilitate decoupling. Therefore, the stipulation that abstractions shouldn’t depend upon details isn’t particularly relevant to JavaScript applications. The stipulation that high level modules shouldn’t depend upon low level modules is, however, relevant.

From a functional point of view, these containers and injection concepts can be solved with a simple higher order function, or hole-in-the-middle type pattern which are built right into the language.”

This principle allows for decoupling. And we have made it before, let’s review our code with the manageShapeInterface and how we accomplish the calculate method.

const manageShapeInterface = (fn) => ({
  type: 'manageShapeInterface',
  calculate: () => fn()
})

What the manageShapeInterface factory function receives as the argument is a higher order function, that decouples for every shape the functionality to accomplish the needed logic to get to final calculation, let see how this is done in the shapes objects.

const square = (radius) => {
  // code
 
  const abstraccion = manageShapeInterface(() => basics.area())
 
 // more code ...
}
const cubo = (length) => {
  // code 
  const abstraccion = manageShapeInterface(
    () => basics.area() + complex.volume()
  )
  // more code ...
}

For the square what we need to calculate is just getting the area of the shape, and what we need is summing the area with the volume and that is everything need to avoid the coupling and get the abstraction.

For Another example, we analyse that the Http Request depends on the setState function, which is a detail. These code violates the Dependency Inversion principle.

http.get("http://address/api/examples", (res) => {
 this.setState({
  key1: res.value1,
  key2: res.value2,
  key3: res.value3
 });
});

The correct code is :

//Http request
const httpRequest = (url, setState) => {
 http.get(url, (res) => setState.setValues(res))
};

//State set in another function
const setState = {
 setValues: (res) => {
  this.setState({
    key1: res.value1,
    key2: res.value2,
    key3: res.value3
  })
 }
}

//Http request, state set in a different function
httpRequest("http://address/api/examples", setState);

That’s all about in this article.


Conclusion

In this article, We understood about the Javascript 5 SOLID Principles. The main goal of the SOLID principles is that any software should tolerate change and should be easy to understand. We conclude that SOLID is very useful for write code :

  • Easy to understand
  • Where things are where they’re supposed to be
  • Where classes do what they were intended to do
  • That can be easily adjusted and extended without bugs
  • That separates the abstraction from the implementation
  • That allows to easily swap implementation (Db, Api, frameworks, …)
  • Easily testable

Thanks for reading !! I hope you enjoyed and learned about SOLID Principles Concept in javascript. 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 !!???

Android – Understanding Platform Architecture

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn about the Android Platform Architecture which supports different mobile device needs. We will discuss about Android Platform Architecture components one by one.

A famous quote about learning is :

” That is what learning is. You suddenly understand something you’ve understood all your life, but in a new way. “


So Let’s begin.

Overview

Android is an open source, Linux-based software stack created for a wide array of devices and form factors. The following diagram shows the major components of the Android platform.

Android software stack contains a Linux Kernel, HAL, collection of c/c++ libraries which are exposed through an application framework services, runtime, and application.

In these components, the Linux Kernel is the main component in android to provide its operating system functions to mobile and Dalvik Virtual Machine (DVM) which is responsible for running a mobile application.

Main Components of Android Architecture

Following are main components of android architecture those are :

  1. Linux Kernel
  2. Hardware Abstraction Layer(HAL)
  3. Native C/C++ Libraries
  4. Android Runtime
  5. Java API Framework
  6. System Apps


1. Linux Kernel

The foundation of the Android platform is the Linux kernel. For example, the Android Runtime (ART) relies on the Linux kernel for underlying functionalities such as threading and low-level memory management.

Using a Linux kernel allows Android to take advantage of key security features and allows device manufacturers to develop hardware drivers for a well-known kernel.

Linux Kernel is a bottom layer and heart of the android architecture. It manages all the drivers such as display drivers, camera drivers, Bluetooth drivers, audio drivers, memory drivers, etc. which are mainly required for the android device during the runtime.

The Linux Kernel will provide an abstraction layer between the device hardware and the remainder of the stack. It is responsible for memory management, power management, device management, resource access, etc.


2. Hardware Abstraction Layer (HAL)

The hardware abstraction layer (HAL) provides standard interfaces that expose device hardware capabilities to the higher-level Java API framework. 

The HAL consists of multiple library modules, each of which implements an interface for a specific type of hardware component, such as the camera or bluetooth module. When a framework API makes a call to access device hardware, the Android system loads the library module for that hardware component.


3. Native C/C++ Libraries

Many core Android system components and services, such as ART and HAL, are built from native code that require native libraries written in C and C++. The Android platform provides Java framework APIs to expose the functionality of some of these native libraries to apps. For example, we can access OpenGL ES through the Android framework’s Java OpenGL API to add support for drawing and manipulating 2D and 3D graphics in our app.

If we are developing an app that requires C or C++ code, we can use the Android NDK to access some of these native platform libraries directly from our native code.

The following are the summary details of some core android libraries available for android development:

  • Media library for playing and recording audio and video formats
  • The Surface manager library to provide a display management
  • SGL and OpenGL Graphics libraries for 2D and 3D graphics
  • SQLite is for database support and FreeType for font support
  • Web-Kit for web browser support and SSL for Internet security.


4.  Android Runtime

For devices running Android version 5.0 (API level 21) or higher, each app runs in its own process and with its own instance of the Android Runtime (ART). 

ART is written to run multiple virtual machines on low-memory devices by executing DEX files, a bytecode format designed specially for Android that’s optimized for minimal memory footprint. Build toolchains, such as Jack, compile Java sources into DEX bytecode, which can run on the Android platform.

Some of the major features of ART include the following points below:

  • Ahead-of-time (AOT) and just-in-time (JIT) compilation
  • Optimized garbage collection (GC)
  • On Android 9 (API level 28) and higher, conversion of an app package’s Dalvik Executable format (DEX) files to more compact machine code.
  • Better debugging support, including a dedicated sampling profiler, detailed diagnostic exceptions and crash reporting, and the ability to set watchpoints to monitor specific fields.

Prior to Android version 5.0 (API level 21), Dalvik was the Android runtime. If our app runs well on ART, then it should work on Dalvik as well, but the reverse may not be true.

Android also includes a set of core runtime libraries that provide most of the functionality of the Java programming language, including some Java 8 language features, that the Java API framework uses.


5. Java API Framework

The entire feature-set of the Android OS is available us through APIs written in the Java language. These APIs form the building blocks we need to create Android apps by simplifying the reuse of core, modular system components and services, which include the following points:

  • A rich and extensible View System we can use to build an app’s UI, including lists, grids, text boxes, buttons, and even an embeddable web browser
  • A Resource Manager, providing access to non-code resources such as localized strings, graphics, and layout files
  • A Notification Manager that enables all apps to display custom alerts in the status bar
  • An Activity Manager that manages the lifecycle of apps and provides a common navigation back stack
  • Content Providers that enable apps to access data from other apps, such as the Contacts app, or to share their own data.

Developers have full access to the same framework APIs that Android system apps use. The application framework includes services like telephony service, location services, notification manager, NFC service, view system, etc. which we can use for application development as per our requirements.


6. System Apps

The top layer of the android architecture is System Applications. The native and third-party applications like contacts, email, music, gallery, clock, games, etc. whatever we will build those will be installed on this layer only.

The application layer runs within the Android run time using the classes and services made available from the application framework. 

The system apps function both as apps for users and to provide key capabilities that developers can access from their own app. For example, if our app would like to deliver an SMS message, we don’t need to build that functionality ourself – we can instead invoke whichever SMS app is already installed to deliver a message to the recipient we specify.

That’s all about in this article.


Conclusion

In this article, We understood about Platform Architecture Concepts in Android. This article demonstrated the main components of android platform architecture which is responsible for running a mobile application.

Thanks for reading ! I hope you enjoyed and learned about the Platform Architecture Concepts in Android. 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!!???

React Native – How To Secure Mobile Application In React Native ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn how to secure Mobile application in React Native. We will discuss Security related areas and techniques to secure mobile application. React Native is a popular cross-platform JavaScript framework. Components of React Native apps are rendered in Native UI. In this article, we will focus on the security side of the framework. In this article, we will focus on the security side of the framework.

A famous quote about learning is :

” Develop a passion for learning. If you do, you will never cease to grow.”

So Let’s begin.


Analyzing React Native

React Native has an alternative approach for cross-platform development. Traditionally, Cordova-based frameworks used WebView to render the whole application. In contrast, React Native applications run the JS code in a JavaScript VM based on JavaScriptCore. The application uses native JavaScriptCore on iOS and JavaScriptCore libs are bundled on an APK on Android.

In React Native, the communication between Native and JavaScript code is handled by a JavaScript Bridge. The source JS files are compiled into one single bundle file known as entry file. In development mode, the file is bundled on a local server and fetched by the application. For production, the application logic is usually bundled in a single file, usually “index.android.bundle” or “index.ios.bundle“. 

Similarly to Cordova, the bundle file is present in the assets folder and, as also happens with Cordova, we can assume React Native apps as containers that run JS code. This logic is implemented in the expo. Under certain limitations, Expo can run different business logic in a single application. At this moment, it’s fair to assume the entry-file as the core application logic.


Major Sections of Secure Mobile Application

Secure Mobile Application is divided into three sections :

  • Securing application to server connection
  • Securing local storage
  • Advanced integrity checks


1. Securing Application to Server Connection

Usually, smartphone apps communicate with the backend server via APIs. Insecure Communication is highlighted in the OWASP Mobile Top 10 at #3:

Mobile applications frequently do not protect network traffic. They may use SSL/TLS during authentication but not elsewhere. This inconsistency leads to the risk of exposing data and session IDs to interception. The use of transport security does not mean the app has implemented it correctly. To detect basic flaws, observe the phone’s network traffic. More subtle flaws require inspecting the design of the application and the applications configuration. – M3-Insecure Communication.

Starting from iOS 9 and Android Pie, SSL is required by default. We can enable cleartext traffic but it’s not recommended. To secure the connection further, we can pin our server certificates.


SSL Pinning in React Native

Apps are dependent on Certificate Authorities (CA) and Domain Name Servers (DNS) to validate domains for TLS. Unsafe certificates can be installed on a user device, thereby opening the device to a Man-in-the-Middle attack. SSL pinning can be used to mitigate this risk.

We use the fetch API or libraries like axios or frisbee to consume APIs in our React Native applications. However, these libraries don’t have support for SSL pinning. Let’s explore the available plugins:

  • react-native-ssl-pinning: this plugin uses OkHttp3 on Android and AFNetworking on iOS to provide SSL pinning and cookie handling. In this case, we will be using fetch from the library to consume APIs. For this library, we will have to bundle the certificates inside the app. Necessary error handling needs to be implemented in older apps to handle certificate expiry. The app needs to be updated with newer certificates before certificates expire. This library uses promises and supports multi-part form data.
  • react-native-pinch: this plugin is similar to react-native-ssl-pinning. We have to bundle certificates inside the app. This library supports both promises and callbacks.

To use HPKP (Http Public Key Pinning), we can consider these plugins:

  • react-native-cert-pinner: this plugin allows us to use public hashes to pin the server. Unlike the plugins above, we can use fetch and other utilities directly. The pinning occurs before native JS is run. Also, there is no requirement to define hashes in the request itself.
  • react-native-trustkit: this is a wrapper plugin for the iOS Trustkit library. This library is available for iOS only.


2. Securing Local Storage

Normally, we store data inside our application to achieve offline functionality. There are multiple ways to store persistent data in React Native. Async-storage, sqlite, pouchdb and realm are some of the methods to store data.

Insecure storage is highlighted at #2 in the OWASP Mobile Top 10:

Insecure data storage vulnerabilities occur when development teams assume that users or malware will not have access to a mobile device’s filesystem and subsequent sensitive information in data-stores on the device. Filesystems are easily accessible. Organizations should expect a malicious user or malware to inspect sensitive data stores. Usage of poor encryption libraries is to be avoided. Rooting or jailbreaking a mobile device circumvents any encryption protections. When data is not protected properly, specialized tools are all that is needed to view application data. – M2-Insecure Data Storage.

Let’s take a look at some plugins which add a layer of security to our application. Also, we will be exploring some plugins which use native security features Keychain and Keystore Access.


SQLite

SQLite is the most common way to store data. A very popular and open-source extension for SQLite encryption is SQLCipher. Data in SQLCipher is encrypted via 256 bit AES which can’t be read without a key. React Native has two libraries that provide SQLCipher:

  • react-native-sqlcipher-2 : this is a fork of react-native-sqlite-2. We can use pouchdb as an ORM provider with this library, so it’s an additional bonus.
  • react-native-sqlcipher-storage : this is a fork of react-native-sqlite-storage. The library has to be set up manually since it doesn’t seem to support react-native link. Interestingly, the library is based on the Cordova implementation.


Realm

Realm is a nice alternative database provider to React Native Apps. It’s much faster than SQLite and it has support for encryption by default. It uses the AES256 algorithm and the encrypted realm is verified using SHA-2 HMAC hash.


Keychain and Keystore Access

Both iOS and Android have native techniques to store secure data. Keychain services allows developers to store small chunks of data in an encrypted database. On Android, most plugins use the Android keystore system for API 23(Marshmallow) and above. For lower APIs, Facebook’s conceal provides the necessary crypto functions. Another alternative is to store encrypted data in shared preferences.

React Native has three libraries that provide secure storage along with biometric/face authentication:

  • React Native KeyChain: As the name implies, this plugin provides access to keychain/keystore. It uses Keychain (iOS), Keystore (Android 23+), and conceal. There is support for Biometric Auth. This plugin has multiple methods and options for both Android and iOS. However, it only allows the storage of the username & password.
  • React Native Sensitive Info: This plugin is similar to React Native Keychain. It uses Keychain (iOS) and shared preferences (Android) to store data. We can store multiple key-value pairs using this plugin.
  • RN Secure Storage: This plugin is similar to React Native Sensitive Info. It uses Keychain (iOS), Keystore (Android 23+), and Secure Preferences to store data. We can store multiple key-value pairs.


3. Advanced Integrity Checks


JailMonkey and SafetyNet

Rooted and jailbroken devices should be considered insecure by intent. Root privileges allow users to circumvent OS security features, spoof data, analyze algorithms, and access secured storage. As a rule of thumb, the execution of the app on a rooted device should be avoided.

JailMonkey allows React Native applications to detect root or jailbreak. Apart from that, it can detect if mock locations can be set using developer tools.

SafetyNet is an Android-only API for detecting rooted devices and boot loader unlocks. 

react-native-google-safetynet is a wrapper plugin for SafetyNet’s attestation API. It can be used to verify the user’s device.

Additionally, we can use react-native-device-info to check if an app is running in an emulator.


Protecting the Application Logic

Earlier in the article, we mentioned how the application logic in entry-file is available in plain sight. In other words, a third-party can retrieve the code, reverse-engineer sensitive logic, or even tamper with the code to abuse the app (such as unlocking features or violating license agreements).

Protecting the application logic is a recommendation in the OWASP Mobile Top 10. Specifically, the main concerns include code tampering:

Mobile code runs within an environment that is not under the control of the organization producing the code. At the same time, there are plenty of different ways of altering the environment in which that code runs. These changes allow an adversary to tinker with the code and modify it at will. — M8-Code Tampering. “

And reverse engineering:

Generally, most applications are susceptible to reverse engineering due to the inherent nature of code. Most languages used to write apps today are rich in metadata that greatly aides a programmer in debugging the app. This same capability also greatly aides an attacker in understanding how the app works. — M9-Reverse Engineering.”

Let’s highlight two different strategies to address this risk.


Hermes

Facebook introduced Hermes with the react-native 0.60.1 release. Hermes is a new JavaScript Engine optimized for mobile apps. Currently, it is only available with Android and it’s usage is optional. Hermes can be used in the project with react-native 0.60.4 by changing the enableHermes flag in build.gradle file.

Its key benefits are improved start-up time, decreased memory usage, and smaller app size. One of the strategies that Hermes uses to achieve this is precompiling JavaScript to bytecode.

Let’s look at a real example. We assume that our entry-file is the one found below:

const {createDecipheriv, createCipheriv, randomBytes} = require('crypto');
const key = Buffer.from('60adba1cf391d89a3a71c72a615cbba8', 'hex');
const algorithm = 'aes-128-cbc';
const softwareVersion = '2.0';
module.exports.createKey = function(userId, expireDate) {
  const payload = {
    userId,
    expireDate,
    softwareVersion
  };
  const json = Buffer.from(JSON.stringify(payload), 'utf8');
  const iv = randomBytes(16);
  const cipher = createCipheriv(algorithm, key, iv);
  let encoded = cipher.update(json);
  encoded = Buffer.concat([encoded, cipher.final()]);
  const joined = iv.toString('hex') + ';' + encoded.toString('hex');
  return Buffer.from(joined, 'utf8').toString('base64');
}
module.exports.validateLicense = function(license, userId) {
  const licenseFields = Buffer.from(license, 'base64').toString('utf8');
  const fields = licenseFields.split(';');
  const iv = Buffer.from(fields[0], 'hex');
  const data = Buffer.from(fields[1], 'hex');
  const decipher = createDecipheriv(algorithm, key, iv);
  let decoded = decipher.update(data);
  decoded = Buffer.concat([decoded, decipher.final()]);
  const result = JSON.parse(decoded);
  if (result.userId != userId) {
    throw new Error('Wrong user');
  }
  if (new Date(result.expireDate) < new Date()) {
    throw new Error('Expired license');
  }
  if (result.softwareVersion != softwareVersion) {
    throw new Error('This license is not valid for this program version');
  }
  return result;
}

After Hermes compiles this file, the resulting bytecode can easily be decompiled using hbcdump and, among the decompiled code, we find some easy to read code look like:

s0[ASCII, 0..-1]: 
s1[ASCII, 0..2]: 2.0
s2[ASCII, 3..34]: 60adba1cf391d89a3a71c72a615cbba8
s3[ASCII, 35..35]: ;
s4[ASCII, 36..50]: Expired license
s5[ASCII, 71..120]: This license is not valid for this program version
s6[ASCII, 121..130]: Wrong user
s7[ASCII, 133..143]: aes-128-cbc
s8[ASCII, 143..148]: crypto
s9[ASCII, 154..159]: global
s10[ASCII, 160..165]: base64
s11[ASCII, 166..168]: hex
s12[ASCII, 177..180]: utf8
i13[ASCII, 50..56] #C765D706: exports
i14[ASCII, 56..70] #FF849242: softwareVersion
i15[ASCII, 127..132] #6FE51CD4: userId
i16[ASCII, 147..154] #1E019520: toString
i17[ASCII, 167..176] #68A06D42: expireDate
i18[ASCII, 173..176] #CD347266: Date
i19[ASCII, 181..186] #5AA7C487: Buffer
i20[ASCII, 186..196] #FD81EB01: randomBytes
i21[ASCII, 196..200] #0EC469F8: split
i22[ASCII, 201..205] #9102A3D0: Error
i23[ASCII, 205..211] #EB75CA32: require
i24[ASCII, 212..215] #971CE5C7: JSON
i25[ASCII, 216..221] #CB8DFA65: concat
i26[ASCII, 222..235] #96C7181F: createCipheriv
i27[ASCII, 235..249] #D60B6B51: validateLicense
i28[ASCII, 250..265] #723D6A80: createDecipheriv
i29[ASCII, 266..274] #01D3AE7D: createKey
i30[ASCII, 275..279] #47993A63: final
i31[ASCII, 280..283] #EAF03666: from
i32[ASCII, 283..288] #2A322C6E: module
i33[ASCII, 289..293] #958EDB02: parse
i34[ASCII, 294..302] #807C5F3D: prototype
i35[ASCII, 303..311] #8D1543BD: stringify
i36[ASCII, 312..317] #60396F4B: update

Function<global>0(1 params, 15 registers, 4 symbols):
Offset in debug table: src 0x0, vars 0x0
license.js[1:1]
    CreateEnvironment r0
    GetGlobalObject   r1
    TryGetById        r4, r1, 1, "require"
    LoadConstUndefined r3
    LoadConstString   r2, "crypto"
    Call2             r2, r4, r3, r2
    GetByIdShort      r3, r2, 2, "createDecipheriv"
    StoreToEnvironment r0, 0, r3
    GetByIdShort      r3, r2, 3, "createCipheriv"
    StoreToEnvironment r0, 1, r3
    GetByIdShort      r2, r2, 4, "randomBytes"
    StoreToEnvironment r0, 2, r2
    TryGetById        r5, r1, 5, "Buffer"
    GetByIdShort      r4, r5, 6, "from"
    LoadConstString   r3, "60adba1cf391d89a3"...
    LoadConstString   r2, "hex"
    Call3             r2, r4, r5, r3, r2
    StoreToEnvironment r0, 3, r2
    TryGetById        r2, r1, 7, "module"
    GetByIdShort      r3, r2, 8, "exports"
    CreateClosure     r2, r0, 1
    PutById           r3, r2, 1, "createKey"
    TryGetById        r1, r1, 7, "module"
    GetByIdShort      r1, r1, 8, "exports"
    CreateClosure     r0, r0, 2
    PutById           r1, r0, 2, "validateLicense"
    Ret               r0

So, while Hermes introduces a certain degree of complexity to the entry-file code, it doesn’t actually conceal the code nor do anything to prevent code tampering, which means that it won’t stop an attacker ⁠— let’s not forget that this is not even the purpose of Hermes.

And this leads us to an approach that obfuscates React Native’s JavaScript source code to effectively mitigate the risk of code tampering and reverse engineering: Jscrambler.


Jscrambler

Jscrambler provides a series of layers to protect JavaScript. Unlike most tools that only include (basic) obfuscation, Jscrambler provides three security layers:

  • Polymorphic JavaScript & HTML5 obfuscation
  • Code locks (domain, OS, browser, time frame)
  • Self-defending (anti-tampering & anti-debugging)

By protecting the source code of React Native apps with Jscrambler, the resulting code is highly obfuscated, as can be observed below:

On top of this obfuscation, there’s a Self-Defending layer that provides anti-debugging and anti-tampering capabilities and enables setting countermeasures like breaking the application, deleting cookies, or destroying the attacker’s environment.

That’s all about in this article.


Conclusion

In this article, We learned how to secure Mobile applications in React Native. We discussed about Mobile application security related areas and techniques for React Native . It provides an overview of techniques to help to secure the React Native application. It’s then crucial to create a threat model , and depending on the application’s use case, employ the required measures to ensure that the application is properly secured.

Thanks for reading ! I hope you enjoyed and learned about the Mobile Application Security concepts in React Native. 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 !!???

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 !!???

React Native – An Overview Of React Native Foundation

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn about the React Native Foundation. We will discuss  about react native core concepts through examples. 

A famous quote about learning is :

I am still learning.

So Let’s begin.


What Is React Native ?

React Native is like React, but it uses native components instead of web components as building blocks. So to understand the basic structure of a React Native app, we need to understand some of the basic React concepts, like JSX, components, state, and props.

If we already know React, we still need to learn some React-Native-specific stuff, like the native components.

Let’s do this thing.

Hello World

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

function HelloWorldApp() {
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text>
        Hello, world!
      </Text>
    </View>
  );
}
export default HelloWorldApp;

What’s going on here?

  1. First of all, we need to import React to be able to use JSX, which will then be transformed to the native components of each platform.
  2. On line 2, we import the Text and View components from react-native.

Then we find the HelloWorldApp function, which is a functional component and behaves in the same way as in React for the web. This function returns a View component with some styles and aText as its child.

The Text component allows us to render a text, while the View component renders a container. This container has several styles applied, let’s analyze what each one is doing.

The first style that we find is flex: 1, the flex prop will define how our items are going to “fill” over the available space along your main axis. Since we only have one container, it will take all the available space of the parent component. In this case, it is the only component, so it will take all the available screen space.

The following style is justifyContent: “center”. This align children of a container in the center of the container’s main axis and finally we have alignItems: “center”, which align children of a container in the center of the container’s cross axis.React Native ships with ES2015 support, so you can use this stuff without worrying about compatibility. importfromclass, and extends in the example above are all ES2015 features.

The other unusual thing in this code example is Hello world!

This is JSX – a syntax for embedding XML within JavaScript. In React, this is reversed. JSX lets you write your markup language inside code. It looks like HTML on the web, except instead of web things like <div> or <span> you use React components. In this case, <text> is a Core Component that displays some text and View is like the <div> or <span>.


React Native Fundamentals

React Native runs on React, a popular open source library for building user interfaces with JavaScript. To make the most of React Native, it helps to understand React itself.

We’re going to cover the core concepts behind React native :

  • Components
  • JSX
  • props
  • state


Components

So HelloWorldApp example code is defining HelloWorldApp, a new Component. When we’re building a React Native app, we’ll be making new components a lot. Anything we see on the screen is some sort of component.


JSX

React and React Native use JSX, a syntax that lets we write elements inside JavaScript like so: <Text>Hello, I am your cat!</Text>.

Because JSX is JavaScript, we can use variables inside it. Here we are declaring a name for the cat, name, and embedding it with curly braces inside <Text>.

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

const Cat = () => {
  const name = "Maru";
  return (
    <Text>Hello, I am {name}!</Text>
  );
}

export default Cat;

Because JSX is included in the React library, it won’t work if we don’t have import React from 'react' at the top of our file!


Props

Most components can be customized when they are created, with different parameters. These creation parameters are called props.

Our own components can also use props. This lets us make a single component that is used in many different places in our app, with slightly different properties in each place. Refer to props.{NAME} in our functional components or this.props.{NAME} in our class components. Here’s an example:

import React from 'react'; import { Text, View, StyleSheet } from 'react-native'; const styles = StyleSheet.create({ center: { alignItems: 'center' } }) function Greeting(props) { return ( <View style={styles.center}> <Text>Hello {props.name}!</Text> </View> ); } function LotsOfGreetings() { return ( <View style={[styles.center, {top: 50}]}> <Greeting name='Rexxar' /> <Greeting name='Jaina' /> <Greeting name='Valeera' /> </View> ); } export default LotsOfGreetings;

Using name as a prop lets us customize the Greeting component, so we can reuse that component for each of our greetings. This example also uses the Greeting component in JSX. The power to do this is what makes React so cool.

The other new thing going on here is the View component. A View is useful as a container for other components, to help control style and layout.

With props and the basic TextImage, and View components, we can build a wide variety of static screens. To learn how to make our app change over time, we need to learn about State.


State

Unlike props that are read-only and should not be modified, the state allows React components to change their output over time in response to user actions, network responses and anything else. Here’s an example:

import React, { Component } from 'react' import { StyleSheet, TouchableOpacity, Text, View, } from 'react-native' class App extends Component { state = { count: 0 } onPress = () => { this.setState({ count: this.state.count + 1 }) } render() { return ( <View style={styles.container}> <TouchableOpacity style={styles.button} onPress={this.onPress} > <Text>Click me</Text> </TouchableOpacity> <View style={styles.countContainer}> <Text> You clicked { this.state.count } times </Text> </View> </View> ) } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, button: { alignItems: 'center', backgroundColor: '#DDDDDD', padding: 10, marginBottom: 10 } }) export default App;

In this example,

  1. First of all, we need to import React to be able to use JSX, which will then be transformed to the native components of each platform.
  2. On line 2, we import the StyleSheet , TouchableOpacity , Text and View components from react-native
  3. In next line , we defines a new class  App which extends from React Component .This block of code defines the components that represent the user interface.
  4. After that, we initialize  our app state variable count  to 0 inside App class using  state  variable.
  5. After that we create  onPress()  method where count  is incremented by 1 and count   value is set in  setState()  method.
  6. After that Inside render()  method that returns a react element , includes:
    • A  return()  that returns the result of layout and UI components.
    • A container View  that supports the layout accessibility controls. It is a fundamental component for building the UI.
    • A  TouchableOpacity  wrapper is used to reduce the opacity of button. Here, onPress method is called using onPress props.
    • A React component Text  for displaying text.
    • A property style  used for styling the components using  StyleSheet class.
    • styles   is used to design individual components.
  7. After that, the  StyleSheet  class creates the style object that controls the layout and appearance of components. It is similar to Cascading Style Sheets (CSS) used on the Web.

That’s all about in this article.


Conclusion

In this article, We have discussed about React Native Foundations Concepts like Components,Props and State through example explanations. So we conclude that

  • Components : Everything is component in React Native.The way in which you create a new component.
  • Props : Most components can be customized when they are created, with different parameters. These creation parameters are called props.
  • State : State allows React components to change their output over time in response to user actions, network responses and anything else.

Thanks for reading ! I hope you enjoyed and learned about the React Native Foundation. 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 !!???

React Native – How React Native Works Internally?

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn about the React Native Internal architecture. This article will discuss React Native internal work flow.

A famous quote about learning is :

” Try to learn something about everything and everything about something. “

So, Let’s Start.

Overview

” React Native is a framework which allows developers to build native apps using javascript.”

So What about Cordova Platform and why would anyone want to use React Native?

The Primary difference between React Native and Cordova based app is that

  • Cordova based apps run inside a Web View. 
  • React Native apps renders using Native View.

React Native Application have direct access to all the native APIs and views offered by the underlying mobile OS. React Native Applications have the same feel and performance as that of a native application.

We can assume that React native might be compiling JS code into respective native code directly. But this would be really hard to achieve since Java and Objective C are strongly typed languages while Javascript is not!

React Native does something much more clever.Essentially React Native uses a set of React components, where each component represents the corresponding native views and components.

For example, a native TextInput will have a corresponding React Native component which can be directly imported into the JS code and used like any other React component. Hence, the developer will be writing the code just like for any other React Web app but the output will be a native application.

To understand this, let us take a look at the architecture and Threading model and how React Native works internally.


Architecture

React Native uses similar architecture for iOS and Android platform. There are three parts to React Native Platform :


1. Native Code/Modules

Most of the native code in case of iOS is written in Objective C or Swift, while in the case of Android it is written in Java. But for writing our React Native app, we would hardly ever need to write native code for iOS or Android.


2. JavaScript VM

  • The JS Virtual Machine that runs all our JavaScript code. On iOS/Android simulators and devices React Native uses JavaScriptCore, which is the JavaScript engine that powers Safari. JavaScriptCore is an open source JavaScript engine originally built for WebKit. 
  • In case of iOS, React Native uses the JavaScriptCore provided by the iOS platform. It was first introduced in iOS 7 along with OS X Mavericks.
  • In case of Android, React Native bundles the JavaScriptCore along with the application. This increases the app size. Hence the Hello World application of RN would take around 3 to 4 megabytes for Android.
  • In case of Chrome debugging mode, the JavaScript code runs within Chrome itself (instead of the JavaScriptCore on the device) and communicates with native code via WebSocket. Here, it will use the V8 engine. This allows us to see a lot of information on the Chrome debugging tools like network requests, console logs, etc.

3. React Native Bridge

React Native bridge is a C++/Java bridge which is responsible for communication between the native and Javascript thread. A custom protocol is used for message passing.


Threading Models

When a React Native application is launched, it spawns up the following threading queues:


1. Main Thread (Native Queue)

  • Main thread gets spawned when application launches. It loads the app and starts the JS thread to execute the JavaScript code.
  • The Native thread also listens to the UI events like ‘press’, ‘touch’ etc. These events are then passed to the JS thread via RN Bridge.
  • Once the Javascript loads, the JS thread sends the information on what needs to be rendered onto the screen.This information is used by a shadow node thread to compute the layout.
  • The Shadow thread is basically like mathematical engine which finally decides on how to compute the view positions.
  • These instructions are then passed back to the main thread to render the view.


2. JavaScript Thread (JS Queue)

  • The Javascript Queue is the thread queue where main bundled JS thread runs. 
  • The JS thread runs all the business logic, i.e., the code we write in React Native. 


3. Custom Native Modules

  • Apart from the threads spawned by React Native, we can also spawn threads on the custom native modules to build to speed up the performance of the application.
  • For Example – Animations are handled in React Native by a separate native thread to offload the work from the JS thread.

That’s all about in this article.


Conclusion

In this article, We understood about React Native Internal Work Flow. We conclude that React Native work flow based on the threading models and process involved between different threads. We can separate React Native into three Parts :

  • React Native-Native Side
  • React Native -JS Side
  • React Native – Bridge

This is also called “3 Parts of React Native”.

Thanks for reading ! I hope you enjoyed and learned about Internal architecture,Threading Models and Process involved in React Native . 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 !!???

A Short Note – React Terminology Cheatsheet

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series(React Terminology Cheatsheet).

In this note series, we will learn about the commonly used React Terminology and definitions. This article will explain some common terminology from ReactJS.

So, Let’s begin.

  • Single-page Application – An application that loads a single HTML page and all the necessary assets (such as Javascript and CSS) required for the application to run.
  • ES6,ES2015,ES2016 – Most recent versions of the ECMAScript Language Specification standard, which is the javascript language is an implementation of.
  • Compiler – A Javascript compiler takes JavaScript code, transforms it and returns JavaScript code in a different format.
  • Bundlers – Bundlers takes JavaScript and CSS code written as separate modules and compile them together into a few files better optimized for the browser.
  • Package Managers – Package Managers are tools that allow you to manage dependencies in your project.
  • CDN – CDN stands for Content Delivery Network. CDNs deliver cached, static content from a network of servers across the globe.
  • Elements – React elements are the building blocks of React applications. An elements describes what you want to see on the screen.React elements are immutable.
  • JSX – Allows us to write HTML like syntax which gets transformed to lightweight Javascript objects.
  • Virtual DOM – A Javascript representation of the actual DOM.
  • React.Component – The way in which you create a new component.
  • render method – Describes what the UI will look like for the particular component.
  • ReactDOM.render – Renders a React component to a DOM node.
  • State – The internal data store (Object) of a component.
  • constructor (this.state) – The way in which you establish the initial state of a component.
  • setState – A helper method used for updating the state of a component and re-rendering the UI.
  • props – The data which is passed to the child component from the parent component.
  • propTypes – Allow you to control the presence or types of certain props passed to the child component.
  • defaultProps – Allows you set default props for your component.
  • props.children – Available on every component. It contains the content between the opening and closing tags of a component.
  • Component Lifecycle
    • componentDidMount – Fired before the component mounted.
    • componentWillUnmount – Fired after the component will unmount.
    • getDerivedStateFromProps – This method fired when the component mounts and whenever the props change. Used to update the state of a component when its props change.
  • Events
    • onClick
    • onSubmit
    • onChange
  • Controlled Component – An input form element whose value is controlled by React
  • Uncontrolled Component – An uncontrolled component works like form elements do outside of React.

Conclusion

In this note series, We understood about the React Terminology Cheatsheet List.

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

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

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of React as below links :

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

Thanks again Reading. HAPPY READING !!???

Exit mobile version