If I had to explain the term “application state”, I would be presumptuous to conclude that the application state is what the application is now, the application state is strongly correlated with time, and the application state is theoretically different at any given moment.

Jquery era

The concept of front-end state management has not been around for a long time, but there have been practices related to front-end state management before the concept of state management appeared. I started to use jquery in 2017. In the era of jquery, we often take a property value of DOM node, and then judge the next operation according to this property value. There’s a lot of places you can take a property value, there’s a lot of places you can change a property value. The state store at that time was fragmented, and it was difficult or cumbersome to deal with states that depended on each other. At this point there is no specification for how to regulate state management and how to organize the project structure.

In general, there is no concept of state management in jquery, the state store is decentralized, and there is no restriction on state access and modification.

backbone

Backbone emerged later with the development of the front-end. In backbone, there is the concept of model. We can store the state in the model, and the data in the model can only be obtained by get and modified by set. Backbone also has the on method on the model. It listens on the data, and when the data changes, it operates on the view within the on listener function. Backbone decouples data from views. It has a qualitative change in state management. Backbone is usually used with jquery.

Backbone, however, only works on the data layer. It does not work on the view layer. The view layer usually uses jquery.

Front-end community modern state management

For the current state management libraries popular in the front-end community, only Redux, MobX, Vuex are analyzed here.

Redux

Redux is a state container based on the Flux idea. Redux stores state in a single store as a JSONable serialized object, which means that Redux stores state in a centralized manner. Redux follows the idea of Flux, which is also a one-way flow of data. If you want to change the state in a store, you must go through the Store’s dispatch method. After calling store.Dispatch, the rootReducer in the store is called, which in turn calls all reducers to generate a new state. In redux, when an action is dispatched, it cannot be determined which reducer responds to the action and how much data it affects. If only a small part of the state in the store needs to be changed at one dispatch, but the state in the store after the dispatch is finished is new compared to the state before, this can be a performance problem at some point. After a store status update, the Store notifys all subscribers that its status has been updated. Using Redux requires you to manually subscribe to the status update. Ideally, manually subscribing to the status would allow the developer to know exactly what he or she wants to do, but as the software iterates, manually subscribing can lead to undersubscribed or oversubscribed views, with undersubscribed views failing to update, and oversubscribed views failing to update.

import { createStore } from 'redux'

// This is a Reducer, which is a side-effect free function that generates a new state based on the current state and action. Redux State should contain only pure JS objects, arrays, and primitive types.
function counterReducer(state = { value: 0 }, action) {
  switch (action.type) {
    case 'counter/incremented':
      return { value: state.value + 1 }
    case 'counter/decremented':
      return { value: state.value - 1 }
    default:
      return state
  }
}

// Create a store to hold the state of the application
const store = createStore(counterReducer)


// Subscribe to the state changes
store.subscribe(() = > console.log(store.getState()))

// You can only change the state of a store by dispatching an action.
store.dispatch({ type: 'counter/incremented' })
Copy the code

The following is a Redux data flow diagram

It can be seen from the figure above that the state modification is carried out in a specific direction. The state change must go through reducers, and the state changes in a predictable way. To summarize the characteristics of Redux state management:

  1. Follow the Flux idea, one-way data flow
  2. Centralized storage management application status
  3. State is the form of a JSON-serializable object
  4. You need to subscribe manually

Mobx

Mobx is another state management library. Mobx has four core concepts: Observable State, Computed Values, Reactions, and Actions. Observable State is the source data, and it can be any value. Computed values are Computed from Observable State and pure functions. Reactions are similar to Computed values in that they are both derived data, but unlike Computed values, Reactions can be a side effect, such as: Network requests, mapping the component tree to the DOM and this is all Reactions. Actions Is used to modify the Observable State. Mobx takes its inspiration from a spreadsheet. All data cells with values are Observable State, and the values in the cells are combined with a formula to produce a Computed values. If you draw a cell’s value to the screen, it’s Reactions, and if you change a cell’s value, it’s Actions.

class Person {
  @observable firstName = "Michel";
  @observable lastName = "Weststrate";
  @observable nickName;
  
  @computed get fullName() {
    return this.firstName + "" + this.lastName; }}const michel = new Person();

// Reaction: log the profile info whenever it changes
autorun(() = > console.log(michel.nickName ? michel.nickName : michel.fullName));

// Example React component that observes state
const profileView = observer(props= > {
  if (props.person.nickName)
    return <div>{props.person.nickName}</div>
  else
    return <div>{props.person.fullName}</div>
});

// Action:
setTimeout(() = > michel.nickName = "mweststrate".5000)

React.render(React.createElement(profileView, { person: michel }), document.body);
Copy the code

There are two major differences between Mobx and Redux:

  1. Mobx does not require that the data structure of the state be JSON-serializable; it can use objects, arrays, and classes. Loop through data structures and references to store state
  2. MobX automatically collects and tracks dependencies, he doesn’t need to manually subscribe to status updates, and can accurately update the affected content when the status changes

When you start using Mobx, it feels very flexible. MobX’s recommended data flow graphs are:

As you can see from the figure above, MobX recommends using Action to modify state, but this is only a limitation in strict mode. If not, there are many places to modify state directly. If you modify the status of a store, the security of the status change is degraded. Mobx focuses only on changes from raw data to derived data, and there is no specification for how you organize your code, and developers with different experiences can write code that varies greatly, which is not good for projects that focus on business logic.

Vuex

Vuex is a plug-in for Vue. It is designed for state management of Vue applications. Like Redux, Vuex centrally stores and manages the state of an application. The only way to change the state in the store is by commit mutation. In this sense, Vuex also follows the Flux idea. Since Vue automatically collects and tracks dependencies while rendering, the state of Vuex is responsive. If a Vue component reads status from a store, when the state in the store changes, the corresponding component is updated.

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // mutate state
      state.count++
    }
  },
  actions: {
    incrementAsync ({ commit }) {
      setTimeout(() = > {
        commit('increment')},1000)
    }
  }
})

store.commit('increment')
store.dispatch('incrementAsync')
Copy the code

The data flow diagram is as follows:

In Redux and MobX, an Action is a virtual concept. In Vuex, an Action is a part of the Store that is designed to do asynchronous operations and can return a promise.

conclusion

Using Redux, MobX, and Vuex for state management, the ability to sense and respond to state changes, and the ability to drive interface changes when used in conjunction with view-layer frameworks or libraries, are just some of the basic features of modern state management libraries. In actual project, we should also pay attention to the organizational structure of the code, especially in some heavy business logic despise figure project standardized, structured business logic is particularly important on development paradigm for complex system structure, make different experience of developers write code were similar, so that the business logic structure simplification. Redux, MobX, and Vuex have more or less some requirements on the organization of the code, but less focus on the structure of the business logic.