1. Past ways of dealing with states

The first option is to attach globalData to the App. This option is to write globalData directly into the App

App.js
App({
  globalData: {
    name: 'Front-end scholar'./ /... other globalData
  },
  / /... other globalData
});

/ / value
var name = getApp().globalData.name;
/ / assignment
getApp().globalData.name = 'Change your name';
Copy the code

The second option is to define one or more libData files for storing data, and build your own wheels

For example libData. Js
module.exports = {
  name: 'Front-end scholar'./ /... other globalData
}
/ /... other

// Easy to use
var store = require('./path/to/lib/libData.js');
/ / value
var name = store.name;
/ / assignment
store.name = 'Change your name';
Copy the code

The third way: save the data to be used on the page data or directly on the page, more scattered and not conducive to management and maintenance, but for super small and need to quickly implement the project is also enough. Don’t laugh, our front end is not afraid to write this

dataInPage.js
Page({
  data: {
    name: 'Front-end scholar'
  },
  name: 'Front-end scholar'
});

/ / value
var name = this.data.name;
var name = this.name;
/ / assignment
this.setData('name'.'Change your name');
this.name = 'Change your name');
Copy the code

2. For handling state data, it is sometimes possible to use a mixture of the above methods, and as the project complexity increases, the state becomes difficult to manage.

Therefore, we need to learn from some excellent and mature schemes existing on the Web side, and today’s protagonist is it, everyone may be familiar with it, welcomeReduxAppearance. All kinds of information on the Internet have been very detailed, those who are not clear must understandRedux, here is only a detailed description of how to use in the small program, and inReactThe usage is very similar because of the core librarymina-redux.jsThat’s how the authors of “influence-validated P-redux” do it, and the wheel is already awesome. The following directly on the code, although the code is much, but has the reference value of the real station, so directly posted.

Do not use any build tools, put all the hooks set by the project in the wechat developer tools, use import and export liberally, now you do not need to write your own build

  • Turn ES6 ES5
  • Style completion is automatic when code is uploaded
  • Code is compressed automatically when uploaded
  • Security domain names, TLS versions, and HTTPS certificates are not verified

The core is Redux, along with several useful libraries, all stripped down from the web without using package management tools such as NPM

Lib folder:
  • Redux.js (core file, required)
  • Redux-logger (core.js, deep-diff.js, defaults.js, diff.js, helpers.js, index.js)
  • Redux-thunk.js (asynchronous action intermediate processing, recommended)
  • Mina-redux.js (core file that synchronizes Redux’s Dispatch and warehouse data to the page, mandatory)
  • Remote-redux-devtool.js (used for remote debugging, you can see the data flow directly, very powerful, optional)
  • Remotedev-server.js (remote debugging service, optional, easy to debug)
  • Regenerator-runtime.js (facebook asynchronous library, not related to Redux, optional, highly recommended)
Write the Type Action Reducer related to redux
App.redux.js (I like to write type action reducer in a file)
/** * Handles the applets life cycle and loads some data */
import regeneratorRuntime from '.. /lib/regenerator-runtime';
import util from '.. /lib/util';
import api from '.. /lib/api';
import { minaScecne } from '.. /config/config';

const WX_SYSTEM_INFO = 'WX_SYSTEM_INFO';
const WX_USER_INFO = 'WX_USER_INFO';
const WX_ON_LAUNCH = 'WX_ON_LAUNCH';

const WX_GET_CODE = 'WX_GET_CODE';
const WX_API_PROMISIFY = 'WX_API_PROMISIFY';

const LOGIN_BEGIN = 'LOGIN_BEGIN';
const LOGIN_PENDING = 'LOGIN_PENDING';
const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
const LOGIN_FAIL = 'LOGIN_FAIL';

1 / / usage
// Without middleware, an action can only be dispatched one at a time
export const wxApiPromisify = (a)= > ({
  type: WX_API_PROMISIFY,
  data: util.initWxMethod()
})

export const wxSystemInfo = (data) = > ({
  type: WX_SYSTEM_INFO,
  data: data
})

export const wxUserInfo = (data) = > ({
  type: WX_USER_INFO,
  data: data
})

export const wxOnLaunch = (data = {}) = > {
  const { scene, query, path } = data;
  Object.keys(minaScecne).map((item= > {
    if (scene.toString() === item) {
      data.sceneText = minaScecne[item]
    }
  }));
  return {
    type: WX_ON_LAUNCH,
    data: data
  }
}

2 / / usage
// call with store.dispatch(actionMethodName) on app. Combine actions
export const login = async dispatch => {
  const wxLoginResult = await wx.async.login();
  await dispatch({
    type: WX_GET_CODE,
    data: wxLoginResult
  })
  await dispatch({
    type: LOGIN_BEGIN,
    data: {
      isFetching: false}})await dispatch({
    type: LOGIN_PENDING,
    data: {
      isFetching: true}})if(wxLoginResult.code){
    try {
      const apiLoginResult = await api.user.login({ code: wxLoginResult.code });
      await dispatch({
        type: LOGIN_SUCCESS,
        data: apiLoginResult
      })
      wx.setStorageSync('token', apiLoginResult.data.token)
    } catch (error) {
      await dispatch({
        type: LOGIN_FAIL,
        data: error
      })
    }
  } else {
    await dispatch({
      type: LOGIN_FAIL,
      data: wxLoginResult.errMsg
    })
  }
}

3 / / usage
// With thunk middleware, an action can be refined into multiple states, such as requests, for handling UI loading
// TODO write a request Action helper.
export const thunkExampleAction = (a)= > (
  async dispatch => {
    const wxLoginResult = await wx.async.login();
    await dispatch({
      type: WX_GET_CODE,
      data: wxLoginResult
    })
    await dispatch({
      type: LOGIN_BEGIN,
      data: {
        isFetching: false}})await dispatch({
      type: LOGIN_PENDING,
      data: {
        isFetching: true}})if(wxLoginResult.code){
      try {
        const apiLoginResult = await api.user.login({ code: wxLoginResult.code });
        await dispatch({
          type: LOGIN_SUCCESS,
          data: apiLoginResult
        })
        wx.setStorageSync('token', apiLoginResult.data.token)
      } catch (error) {
        await dispatch({
          type: LOGIN_FAIL,
          data: error
        })
      }
    } else {
      await dispatch({
        type: LOGIN_FAIL,
        data: wxLoginResult.errMsg
      })
    }
  }
);

// The warehouse data structure is predefined
const initState = {
  wxApiPromisify: {
    isFinish: false
  },
  wxSystemInfo: {},
  wxUserInfo: {},
  wxOnLaunch: {},
  wxLogin: {
    code: null.token: null.userId: null.phone: null.errMsg: null
  },
  userLogin: {
    isFetching: false.data: null}};export const appReducer = (state = initState, action) = > {
  switch (action.type) {
    case WX_API_PROMISIFY:
      return Object.assign({}, state, { wxApiPromisify: { isFinish: action.data } });
    case WX_GET_CODE:
      return Object.assign({}, state, { wxLogin: action.data });
    case WX_SYSTEM_INFO:
      return Object.assign({}, state, { wxSystemInfo: action.data});
    case WX_USER_INFO:
      return Object.assign({}, state, { wxUserInfo: action.data});
    case WX_ON_LAUNCH:
      return Object.assign({}, state, { wxOnLaunch: action.data});
    case LOGIN_BEGIN:
      var userLogin = action.data;
      userLogin.isFetching = false;
      return Object.assign({}, state, { userLogin });
    case LOGIN_PENDING:
      var userLogin = action.data;
      userLogin.isFetching = true;
      return Object.assign({}, state, { userLogin });
    case LOGIN_SUCCESS:
      var userLogin = action.data;
      userLogin.isFetching = false;
      return Object.assign({}, state, { userLogin });
    case LOGIN_FAIL:
      var userLogin = action.data;
      userLogin.isFetching = false;
      return Object.assign({}, state, { userLogin });
    default:
      returnstate; }};Copy the code
App.js applets start entry
import regeneratorRuntime from './lib/regenerator-runtime';
import util from './lib/util';  // A custom tool library
import { createStore, applyMiddleware, combineReducers, compose } from './lib/redux';
import thunk from './lib/redux-thunk';
import { Provider } from './lib/mina-redux';

// All reducer reducer is divided into two categories: small program related and business related
import { appReducer } from './redux/app.redux';
import { channelReducer } from './redux/channel.redux';
import { practiceReducer } from './redux/practice.redux';

// Common actions related to the applets project, such as processing the applets startup option, applets API Promise, system information, applets user information, API login, etc
import { wxOnLaunch, wxApiPromisify, wxSystemInfo, wxUserInfo, login } from './redux/app.redux';

import composeWithDevTools from './lib/remote-redux-devtool';
import logger from './lib/redux-logger/index';

// Create a repository
export const store = createStore(combineReducers({
  appReducer,
  channelReducer,
  practiceReducer,
}), compose(
  applyMiddleware(thunk, logger),
  composeWithDevTools({ hostname: '127.0.0.1'.port: 8080.secure: false}))); App(Provider(store)({async onLaunch(option) {
    // Handle the applet to start option
    store.dispatch(wxOnLaunch(option));
    
    // Applet API Promise
    store.dispatch(wxApiPromisify());

    // Get applets system information
    store.dispatch(wxSystemInfo(wx.getSystemInfoSync()));

    // Get applets user information
    store.dispatch(wxUserInfo(await wx.async.getUserInfo()));

    // User login (applet login + API login)login(store.dispatch); }}));Copy the code
Home. Js page
import regeneratorRuntime from '.. /.. /lib/regenerator-runtime';
import util from '.. /.. /lib/util';
import { connect } from '.. /.. /lib/mina-redux';
import { getChannelList } from '.. /.. /redux/channel.redux';

const pageConfig = {
  data: {
    userLogin: {
      data: null,},channelList: {
      data: [].isFetching: false,}},async onLoad(option) {
    try {
      console.log(` ${getCurrentPages().slice(- 1) [0] ['__route__']} onLoad`);
      util.initPageOnLoad.call(this, option);

      wx.showLoading({
        title: 'Loading... '.mask: true});// First of all, all back-end API calls must be made after login, here first wait for the app life cycle to get the login permission token
      await util.waitfor(this.data, ['userLogin'.'data'.'token'].0.null.50);

      // Then you can happily stream various API data,
      await this.getChannelList();
      wx.hideLoading();
    } catch (error) {
      console.error(`  `, error);
      // TODO}}}// Define the page data, this is automatically injected into the page data, use whatever you need, it is said that the small program has page data performance bottleneck, as needed injection
const mapStateToPage = state= >({... state.appReducer, ... state.channelReducer, });ActionName (param); // Define the method on the page, just this. ActionName (param)
const mapDispatchToPage = dispatch= > ({
  getChannelList: async() = > {awaitdispatch(getChannelList()); }});/ / string up
const nextConfig = connect(mapStateToPage, mapDispatchToPage)(pageConfig);

Page(nextConfig);
Copy the code

3. Although the code is very long, it may look uncomfortable, but I think it is much more elegant than before. It is good to be familiar with it a little.^ _ ^) hee hee…

Start debugging, then visit http://localhost:8080 in your browser, or use the Redux DevTools debugging plug-in
$ npm install -g remotedev-server 
$ remotedev --hostname=localhost --port=8080

[Busy] Launching SocketCluster
   [Active] SocketCluster started
            Version: 6.8. 0
            Environment: dev
            WebSocket engine: uws
            Port: 8080
            Master PID: 14961
            Worker count: 1
            Broker count: 1
Copy the code
Wechat developer tool AppData Pages /home/home data screenshot

Screenshot of wechat developer tool Console log

Redux RemoteDev state data structure Chart

Redux RemoteDev action timeline and Tree structure

Redux RemoteDev tool Log monitor

Redux DevTools has a lot of great features like the legendary “time travel” and can do a lot of fun things

THANKS

[tutorial] wechat applet integration with Redux, introducing rich peripheral tools