关于react.js:usePolymerAction

60次阅读

共计 7526 个字符,预计需要花费 19 分钟才能阅读完成。

背景

随着 React Hooks 遍及起来,组件逻辑写法变成函数式;逻辑函数申明、函数代码构造 ,随着逻辑减少简单,代码组织凌乱,函数申明散乱;
最要害的一点,每个人对代 码了解不一样 ,有的喜爱在一个function 写大段逻辑,有的喜爱拆分逻辑很细,
就会使在我的项目保护时 ,代码格调、代码构造,越来越不对立,难以保护
针对上述情况,须要能够组织代码结、梳理逻辑的办法,从而达到我的项目维护性高、代码构造对立、逻辑清晰

设计理念

形象代码构造

在编写代码的过程中,发现能够形象出公共代码构造;

  1. 申明可变数据/ 共享变量申明、state 申明 /let xxx= xxx/useState
  2. 办法申明/function xx () {} /action/dispatch
  3. 办法调用 / xx() / action()/dispatch()

通过上图,能够把常见组件外部逻辑,分成 3 个局部,其中 3、4 属于雷同局部:

  1. :次要是申明数据,有 useState/let xxx = 11;
  2. :申明函数、办法,会波及批改数据**setcounts**、应用数据**sendLogcount**;

    1. 其中批改与应用里会有一些辅助办法 fetch 来执行对应逻辑;
  3. 调用办法 3 与 4 局部都在视图中应用函数与办法,对立称为调用办法。

把代码构造拆分、剖析之后;其实在日常的开发过程中大部分代码简单逻辑都在 1 与 2 局部,而 2 局部里有互相调用的逻辑,各种辅助函数互相杂糅在一起, 缓缓的使得代码越来越简单,难以浏览。

申明与定义

咱们能够把 1 与 2 局部简单封装起来,定义好标准洁净的构造如

依据上图可知,把原先 1、2、3 局部对立封装在一个 hooks.js 文件里;

  • 原先 1 与 2 局部代码通过调用 **polymerAction** 给聚合起来,把 state 与 actions/ 办法申明给放在一起;再通过 **const [state, actions, shareVars] = usePolymerActionState(countActions)** 对外裸露数据与 acions/ 办法。
  • 原先 3 局部封装 hooks 应用 **usePolymerActionState** 裸露办法调用,走失常调用逻辑
  • 在视图里,失常应用 hooks 封装办法,**return****usePolymerActionState** 裸露数据与办法,失常调用逻辑。

能够看出 外围局部 ,就是把state 与 action 封装在一起高内聚,通过对象组织代码构造,而对象能够进行 组合形式,来组织更大简单的代码逻辑与构造。
从视图上来看,只调用裸露进去的办法。
总结一下,依照上述形式,能够进步我的项目可维护性,代码构造对立。

用法

/** @jsx createElement */
import {createElement, useEffect, useState, useRef, useMemo} from 'rax';
import {moduleInit} from './utils';
export default function Whrealtimetrendinghotels(props) {const { gdc, mds, pageUtils} = props;
  moduleInit({
    gdc,
    mds,
    pageUtils
  })(useState, useEffect, useRef,useMemo);

  return (<CustomComponent
   
  />);
}

入口文件须要在 moduleInit 传入 useMemo, 留神传入地位, 间接依照上述地位传入即可。
ps:为了兼容小程序,在小程序里,库不能间接引入import {createElement, useEffect, useState, useRef, useMemo} from 'rax';

import {initHooksAction} from './hooks';
function CustomComponent(props) {
  const [count, {setCounts, sendLog}
  ] = initHooksAction();

 return (<View style={{width: 100, height: 100, backgroundColor: 'red'}} onClick={() => {setCounts('参入数据了');
 }}>
   
   <Text>{count}</Text>
</View>
 
 
 );

}

initHooksAction能够拿到数据、办法;走失常逻辑;

const countActions = polymerAction({count: 0}, {setCounts({state, setState}, params) {
    setState({count: ++state.count})
    console.log(params)
  },
  fetch({state, setState}, count) {
    console.log(` 接口申请埋点 ${count}`)
  },
  sendLog({state, setState, actions}, count) {actions.fetch(count)
    console.log(` 发送相干埋点 ${count}`)
  },
}, {});

function initHooksAction() {const [state, actions, shareVars] = usePolymerActionState(countActions);
  useEffect(() => {sendLog(state.count);
  }, [state.count])
  return [state.count, actions, shareVars]
}
  • polymerAction:申明 state、actions、shareVar;
  • usePolymerActionState: 底层会重写 actions 办法,shareVar 数据,

    • 返回数据是对应 polymerAction 里申明的数据、办法
  • initHooksAction:封装 hooks 逻辑

    高级用法

    拆分 / 合并 action

    const infiniteScrollAction = polymerAction({
    isLoadingShow: false,
    isLoadingError: false,
    isEmptyData: false,
    }, {showLoading({ state, setState, shareVars, actions}) {
      setState({
        isLoadingShow: true,
        isLoadingError: false,
        isEmptyData: false
      });
    },
    closeLoading({state, setState, shareVars, actions}) {
      setState({isLoadingShow: false});
      shareVars.throttleTarget = true;
    },
    ...,
    }, {throttleTarget: true,});
    const handleAction = polymerAction({},{
    /**
     *  刷新接口
     */
    onRefreshList({state, setState, shareVars, actions}) {....},
    },{})
    const scrollListAction = polymerAction({cityList: [],
    recommendList: [],
    isCityListShow: false,
    }, {initListParam({ state, setState, shareVars, actions}) {
      shareVars.pageNo = 0;
      shareVars.dataVersion = 0;
    },
    
    exp({state, setState, shareVars, actions}, data) {const {cityName, cityCode} = shareVars.cityData;
      let shidsArr = [];
      if (data[0] && data[0].hotHotelList) {shidsArr = hotCityListShids(data);
        sendUT.exp(cityName, shidsArr[0].join('/'), shidsArr[1].join('/'));
      } else {shidsArr = shids(data);
        sendUT.exp(cityName, '', shidsArr.join('/'));
      }
    },
    ...,
    }, {
    pageNo: 0,
    dataVersion: 0,
    cityData: {
      cityName: '',
      cityCode: '',
    }
    });
    function initEffect(param) {const [state, action] = usePolymerActionState(mergePolymerAction(scrollListAction,infiniteScrollAction,handleAction));
    ...
    ...
    return [state, action]
    }
    

    通过 **mergePolymerAction** 能够把多个 action,scrollListActioninfiniteScrollActionhandleAction 合并;这样就能够任意拆分action。

    API

    useSetState

    治理 object 类型 state 的 Hooks,用法与 class 组件的 this.setState 基本一致。

const [state,setState] = useSetState({
 hehe:1,
 aaa:1
});
// 批改
setState({aaa:2})

getAction

从 polymerAction 里,获取 actions

const handleAction = polymerAction({},{
  /**
   *  刷新接口
   */
  onRefreshList({state, setState, shareVars, actions}) {....},
},{});

const handle = getAction(handleAction);

console.log(handle);

,{
  /**
   *  刷新接口
   */
  onRefreshList({state, setState, shareVars, actions}) {....},
}

polymerAction

生成 action 汇合

const scrollListAction = polymerAction({cityList: [],
  recommendList: [],
  isCityListShow: false,
}, {initListParam({ state, setState, shareVars, actions}) {
    shareVars.pageNo = 0;
    shareVars.dataVersion = 0;
  },
  ...,
}, {
  pageNo: 0,
  dataVersion: 0,
  cityData: {
    cityName: '',
    cityCode: '',
  }
});
const [state,actions,shareVal] = polymerAction(stateObj,actionObj,shareValObj)

Params

参数 阐明 类型 默认值
stateObj 必传, 申明 state object {}
actionObj 必传,申明办法、函数 object {}
shareValObj 可选项,传入默认的状态值 boolean {}

Result

参数 阐明 类型
state 状态值 object
actions 操作汇合 Actions
shareVal 共享变量 object

actionObj

const handleAction = polymerAction({},{
  /**
   *  刷新接口
   */
  onRefreshList({state, actions,shareVars,setState,setShareVars},param) {...},
     /**
   *  接口报错,刷新接口
   */
  onRefreshListError({state, setState, shareVars, actions}) {actions.getList(true);
  },
},{});
参数 阐明 类型
state 获取 stateObj **object**
actions 获取 actionObj **object**
shareVars 获取 shareValObj **object**
setState 设置 state **({}) => void**
setShareVars 设置 shareVal **({}) => void**

usePolymerActionState

依据传入action,转换成能扭转页面的**PolymerActionState**

function initEffect(param) {const [state, actions] = usePolymerActionState(scrollListAction);
  ...
  ...
  return [state, action]
}
const [state, actions,shareVal] = usePolymerActionState(polymerAction);

Params

参数 阐明 类型
polymerAction 必传, 申明polymerActionState 汇合 **Array**

Result

参数 阐明 类型
state 状态值 **object**
actions 操作汇合 **object**
shareVal 共享变量 **object**

mergePolymerAction

合并多个 **polymerAction**

mergePolymerAction(scrollListAction,infiniteScrollAction,handleAction)

injectState

应用 rax 体系,须要从外手动传newUseState, newUseRef, newUseMemo, 是为了兼容小程序不报错

injectState(useState,useRef,useMemo);

代码



let useState = null;
let useRef = null;
let useMemo = null;
function useSetState(initData) {const [state, setState] = useState(initData);
  const dispatch = (next) => {if ( typeof next === 'object') {setState((pre) => Object.assign({}, pre, next));
    }
    else {setState(next);
    }
  };
  return [state, dispatch];
}

function polymerAction(state, action = {}, shareVar = {}) {return [state, action, shareVar];
}

function newActionData(actions, states, shareVars, setState) {let newAction = {};
  Object.keys(actions)
    .forEach((name) => {const old = actions[name];
      if (typeof old === 'function') {
        // 从新写 actions 办法
        newAction[name] = function(...arg) {
          return old.call(null, {
            state: states,
            shareVars,
            actions: newAction,
            setState(param, fn = () => {}) {setState(param);
              fn(param);
            },
            setShareVars(param) {shareVars = Object.assign(shareVars, param);
            },
          }, ...arg);
        };
      }
    });
  return newAction;
}

// 与 hooks 关联
function usePolymerActionState(param) {const [state, action = {}, shareVar = {}] = param;
  const actions = action;
  // Object.assign({}, xxx) 多个加载反复组件生成对应数据, 避免数据互相笼罩状况
  const [states, setState] = useSetState(Object.assign({}, state));
  // 生成新共享变量
  const shareVars =  useMemo(() => (Object.assign({}, shareVar)), []) ;
  shareVars.updateAfterState = states;
  const newAction =  useMemo(() => (newActionData(actions, states, shareVars, setState)), [action, states, shareVars])

  return [states, newAction, shareVars];
}

function getAction(polymer) {return polymer[1];
}

function mergePolymerAction(action1, ...res) {const actions = action1.map(function (val, index) {let resAction = {};
    res.forEach((action) => {Object.assign(resAction, action[index]);
    });
    return Object.assign({}, val, resAction);
  });
  return actions;
}


function injectState(newUseState, newUseRef, newUseMemo) {if (!newUseState || !newUseMemo) {
    console.warn(` 请在模块中的 moduleInit 传入 useState、useMemo,如:moduleInit({gdc,mds,pageUtils})
    (useState, useEffect, useRef, useMemo);`);
    return
  }
  useState = newUseState;
  useRef = newUseRef;
  useMemo = newUseMemo;
}

export {
  useSetState,
  getAction,
  polymerAction,
  usePolymerActionState,
  mergePolymerAction,
  injectState
};

github

https://github.com/NoahsDante…
如果对你有帮忙请点 start 🙏

正文完
 0