Monday, 11 June 2018

React Context API

Context provides a way to pass data through the component tree without having to pass props down manually at every level.
In a typical React application, data is passed top-down (parent to child) via props, but this can be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required by many components within an application. Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree.
When to Use Context
Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language. For example, in the code below we manually thread through a “theme” prop in order to style the Button component:
class App extends React.Component {
  render() {
    return <Toolbar theme="dark" />;
  }
}

function Toolbar(props) {
  // The Toolbar component must take an extra "theme" prop
  // and pass it to the ThemedButton. This can become painful
  // if every single button in the app needs to know the theme
  // because it would have to be passed through all components.
  return (
    <div>
      <ThemedButton theme={props.theme} />
    </div>
  );
}

function ThemedButton(props) {
  return <Button theme={props.theme} />;
}
Using context, we can avoid passing props through intermediate elements:
// Context lets us pass a value deep into the component tree
// without explicitly threading it through every component.
// Create a context for the current theme (with "light" as the default).
const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    // Use a Provider to pass the current theme to the tree below.
    // Any component can read it, no matter how deep it is.
    // In this example, we're passing "dark" as the current value.
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// A component in the middle doesn't have to
// pass the theme down explicitly anymore.
function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton(props) {
  // Use a Consumer to read the current theme context.
  // React will find the closest theme Provider above and use its value.
  // In this example, the current theme is "dark".
  return (
    <ThemeContext.Consumer>
      {theme => <Button {...props} theme={theme} />}
    </ThemeContext.Consumer>
  );
}
Note
Don’t use context just to avoid passing props a few levels down. Stick to cases where the same data needs to be accessed in many components at multiple levels.

API

React.createContext

const {Provider, Consumer} = React.createContext(defaultValue);
Creates a { Provider, Consumer } pair. When React renders a context Consumer, it will read the current context value from the closest matching Provider above it in the tree.
The defaultValue argument is only used by a Consumer when it does not have a matching Provider above it in the tree. This can be helpful for testing components in isolation without wrapping them. Note: passing undefined as a Provider value does not cause Consumers to use defaultValue.

Provider

<Provider value={/* some value */}>
A React component that allows Consumers to subscribe to context changes.
Accepts a value prop to be passed to Consumers that are descendants of this Provider. One Provider can be connected to many Consumers. Providers can be nested to override values deeper within the tree.

Consumer

<Consumer>
  {value => /* render something based on the context value */}
</Consumer>
A React component that subscribes to context changes.
Requires a function as a child. The function receives the current context value and returns a React node. The value argument passed to the function will be equal to the value prop of the closest Provider for this context above in the tree. If there is no Provider for this context above, the value argument will be equal to the defaultValue that was passed to createContext().
Note
For more information about the ‘function as a child’ pattern, see render props.
All Consumers that are descendants of a Provider will re-render whenever the Provider’s value prop changes. The propagation from Provider to its descendant Consumers is not subject to the shouldComponentUpdate method, so the Consumer is updated even when an ancestor component bails out of the update.
Changes are determined by comparing the new and old values using the same algorithm as Object.is.

Flux Concepts


These are the important high-level concepts and principles you should know about when writing applications that use Flux.

Overview

Flux is a pattern for managing data flow in your application. The most important concept is that data flows in one direction. As we go through this guide we'll talk about the different pieces of a Flux application and show how they form unidirectional cycles that data can flow through.

Flux Parts

  • Dispatcher
  • Store
  • Action
  • View

Dispatcher

The dispatcher receives actions and dispatches them to stores that have registered with the dispatcher. Every store will receive every action. There should be only one singleton dispatcher in each application.
Example:
  1. User types in title for a todo and hits enter.
  2. The view captures this event and dispatches an "add-todo" action containing the title of the todo.
  3. Every store will then receive this action.

Store

A store is what holds the data of an application. Stores will register with the application's dispatcher so that they can receive actions. The data in a store must only be mutated by responding to an action. There should not be any public setters on a store, only getters. Stores decide what actions they want to respond to. Every time a store's data changes it must emit a "change" event. There should be many stores in each application.
Examples:
  1. Store receives an "add-todo" action.
  2. It decides it is relevant and adds the todo to the list of things that need to be done today.
  3. The store updates its data and then emits a "change" event.

Actions

Actions define the internal API of your application. They capture the ways in which anything might interact with your application. They are simple objects that have a "type" field and some data.
Actions should be semantic and descriptive of the action taking place. They should not describe implementation details of that action. Use "delete-user" rather than breaking it up into "delete-user-id", "clear-user-data", "refresh-credentials" (or however the process works). Remember that all stores will receive the action and can know they need to clear the data or refresh credentials by handling the same "delete-user" action.
Examples:
  1. When a user clicks "delete" on a completed todo a single "delete-todo" action is dispatched:
  {
    type: 'delete-todo',
    todoID: '1234',
  }

Views

Data from stores is displayed in views. Views can use whatever framework you want (In most examples here we will use React). When a view uses data from a store it must also subscribe to change events from that store. Then when the store emits a change the view can get the new data and re-render. If a component ever uses a store and does not subscribe to it then there is likely a subtle bug waiting to be found. Actions are typically dispatched from views as the user interacts with parts of the application's interface.
Example:
  1. The main view subscribes to the TodoStore.
  2. It accesses a list of the Todos and renders them in a readable format for the user to interact with.
  3. When a user types in the title of a new Todo and hits enter the view tells the Dispatcher to dispatch an action.
  4. All stores receive the dispatched action.
  5. The TodoStore handles the action and adds another Todo to its internal data structure, then emits a "change" event.
  6. The main view is listening for the "change" event. It gets the event, gets new data from the TodoStore, and then re-renders the list of Todos in the user interface.

Flow of data

We can piece the parts of Flux above into a diagram describing how data flows through the system.
  1. Views send actions to the dispatcher.
  2. The dispatcher sends actions to every store.
  3. Stores send data to the views.
  • (Different phrasing: Views get data from the stores.)
Data flow within Flux application

Sunday, 30 July 2017

Angular JS: Understanding service types (Provider, Factory, Services)

Angular comes with different types of services. Each one with its own use cases.
Something important that you have to keep in mind is that the services are always singleton, it doesn’t matter which type you use. This is the desired behavior.
NOTE: A singleton is a design pattern that restricts the instantiation of a class to just one object. Every place where we inject our service, will use the same instance.

Provider

Provider is the parent of almost all the other services (all but constant) and it is also the most complex but more configurable one.
Let’s see a basic example:
app.provider('foo', function() {

  return {
    
    $get: function() {
      var thisIsPrivate = "Private";
      function getPrivate() {
        return thisIsPrivate;
      }
  
      return {
        variable: "This is public",
        getPrivate: getPrivate
      };
    } 
    
  };

});
provider on its simplest form, just needs to return a function called $get which is what we inject on the other components. So if we have a controller and we want to inject this foo provider, what we inject is the $get function of it.
Why should we use a provider when a factory is much simple? Because we can configure a provider in the config function. We can do something like this:
app.provider('foo', function() {
  
  var thisIsPrivate = "Private";

  return {
    
    setPrivate: function(newVal) {
      thisIsPrivate = newVal; 
    },
    
    $get: function() {
      function getPrivate() {
        return thisIsPrivate;
      }
  
      return {
        variable: "This is public",
        getPrivate: getPrivate
      };
    } 
    
  };

});

app.config(function(fooProvider) {
  fooProvider.setPrivate('New value from config');
});
Here we moved the thisIsPrivate outside our $get function and then we created a setPrivate function to be able to change thisIsPrivate in a config function. Why do we need to do this? Won’t it be easier to just add the setter in the $get? This has a different purpose.
Imagine we want to create a generic library to manage our models and make some REST petitions. If we hardcode the endpoints URLs, we are not making it any generic, so the idea is to be able to configure those URLs and to do so, we create a provider and we allow those URLs to be configured on a config function.
Notice that we have to put nameProvider instead of just name in our config function. To consume it, we just need to use name.
Seeing this we realize that we already configured some services in our applications, like $routeProvider and $locationProvider, to configure our routes and html5mode respectively.
Providers have two different places to make injections, on the provider constructor and on the $get function. On the provider constructor we can only inject other providers and constants (is the same limitation as the config function). On the $get function we can inject all but other providers (but we can inject other provider’s $get function).
Remember: To inject a provider you use: name + ‘Provider’ and to inject its $get function you just use name

Try it


Factory

Provider are good, they are quite flexible and complex. But what if we only want its $getfunction? I mean, no configuration at all. Well, in that cases we have the factory. Let’s see an example:
Example:
app.factory('foo', function() {
  var thisIsPrivate = "Private";
  function getPrivate() {
    return thisIsPrivate;
  }
  
  return {
    variable: "This is public",
    getPrivate: getPrivate
  };
});

// or..

app.factory('bar', function(a) {
  return a * 2;
});
As you see, we moved our provider $get function into a factory so we have what we had on the first provider example but with a much simpler syntax. In fact, internally a factory is a provider with only the $get function.
As I said before, all types are singleton, so if we modify foo.variable in one place, the other places will have that change too.
We can inject everything but providers on a factory and we can inject it everywhere except on the provider constructor and config functions.

Try it


Value

Factory is good, but what if I just want to store a simple value? I mean, no injections, just a simple value or object. Well angular has you covered with the value service:
Example:
app.value('foo', 'A simple value');
Internally a value is just a factory. And since it is a factory the same injection rules applies, AKA can’t be injected into provider constructor or config functions.

Try it


Service

So having the complex provider, the more simple factory and the value services, what is the service service? Let’s see an example first:
Example:
app.service('foo', function() {
  var thisIsPrivate = "Private";
  this.variable = "This is public";
  this.getPrivate = function() {
    return thisIsPrivate;
  };
});
The service service works much the same as the factory one. The difference is simple: The factory receives a function that gets called when we create it and the service receives a constructor function where we do a new on it (actually internally is uses Object.create instead of new).
In fact, it is the same thing as doing this:
app.factory('foo2', function() {
  return new Foobar();
});


function Foobar() {
  var thisIsPrivate = "Private";
  this.variable = "This is public";
  this.getPrivate = function() {
    return thisIsPrivate;
  };
}
Foobar is a constructor function and we instantiate it in our factory when angular processes it for the first time and then it returns it. Like the service, Foobar will be instantiated only once and the next time we use the factory it will return the same instance again.
If we already have the class and we want to use it in our service we can do that like the following:
app.service('foo3', Foobar);
If you’re wondering, what we did on foo2 is actually what angular does with services internally. That means that service is actually a factory and because of that, same injection rules applies.

Try it


Constant

Then, you’re expecting me to say that a constant is another subtype of provider like the others, but this one is not. A constant works much the same as a value as we can see here:
Example:
app.constant('fooConfig', {
  config1: true,
  config2: "Default config2"
});
So… what’s the difference then? A constant can be injected everywhere and that includes provider constructor and config functions. That is why we use constant services to create default configuration for directives, because we can modify those configuration on our config functions.
You are wondering why it is called constant if we can modify it and well that was a design decision and I have no idea about the reasons behind it.

Try it


Bonus 1: Decorator

So you decided that the foo service I sent to you lacks a greet function and you want it. Will you modify the factory? No! You can decorate it:
app.config(function($provide) {
  $provide.decorator('foo', function($delegate) {
    $delegate.greet = function() {
      return "Hello, I am a new function of 'foo'";
    };
    
    return $delegate;
  });
});
$provide is what Angular uses internally to create all the services. We can use it to create new services if we want but also to decorate existing services. $provide has a method called decorator that allows us to do that. decorator receives the name of the service and a callback function that receives a $delegate parameter. That $delegate parameter is our original service instance.
Here we can do what we want to decorate our service. In our case, we added a greet function to our original service. Then we return the new modified service.
Now when we consume it, it will have the new greet function as you will see in the Try it.
The ability to decorate services comes in handy when we are consuming 3rd party services and we want to decorate it without having to copy it in our project and then doing there the modifications.
Note: The constant service cannot be decorated.

Try it


Bonus 2: Creating new instances

Our services are singleton but we can create a singleton factory that creates new instances. Before you dive deeper, keep in mind that having singleton services is the way to go and we don’t want to change that. Said that, in the rare cases you need to generate new instances, you can do that like this:
// Our class
function Person( json ) {
  angular.extend(this, json);
}

Person.prototype = {
  update: function() {
    // Update it (With real code :P)
    this.name = "Dave";
    this.country = "Canada";
  }
};

Person.getById = function( id ) {
  // Do something to fetch a Person by the id
  return new Person({
    name: "Jesus",
    country: "Spain"
  });
};

// Our factory
app.factory('personService', function() {
  return {
    getById: Person.getById
  };
});
Here we create a Person object which receives some json to initialize the object. Then we created a function in our prototype (functions in the prototype are for the instances of the Person) and a function directly in Person (which is like a class function).
So we have a class function that will create a new Person object based on the id that we provide (well, it will in real code) and every instance is able to update itself. Now we just need to create a service that will use it.
Every time we call personService.getById we are creating a new Person object, so you can use this service in different controllers and even when the factory in a singleton, it generates new objects.
Kudos to Josh David Miller for his example.

Try it

Conclusion

Services are one of the coolest features of Angular. We have a lot of ways to create them, we just need to pick the correct one for our use cases and implement it.