useState,useEffect,useReduce手写实现

// ----------useState----------------- let state = []; // 对应值 let setters = []; // 对应设置状态值方法 let stateIndex = 0; function createSetter(index) { return function (newState) { state[index] = newState; // 状态更改后重新渲染视图 render(); }; }function useState(initialState) { // state = state ? state : initialState; state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialState; // function setState(newState) { //console.log(newState); //state = newState; //// 状态更改后重新渲染视图 //render(); // } setters.push(createSetter(stateIndex)); let value = https://www.it610.com/article/state[stateIndex]; let setter = setters[stateIndex]; stateIndex++; return [value, setter]; }// --------------useEffect----------------- // 上一次的依赖值 let prevDepsAry = []; // 结果应该为一个二位数组 let effectIndex = 0; function useEffect(callback, depsAry) { // 判断callback是不是函数 if (Object.prototype.toString.call(callback) !=="[object Function]") { throw new Error("useEffect函数的第一个参数必须是函数"); } // 判断depsAry有没有被传递 if (typeof depsAry === "undefined") { // 没有传递 callback(); } else { // 判断depsAry是不是数组 if (Object.prototype.toString.call(depsAry) !== "[object Array]") { throw new Error("useEffect函数的第二个参数必须是数组"); } // 获取上一次的状态值 let prevDeps = prevDepsAry[effectIndex]; // 将当前的依赖值和上一次的依赖值做对比 如果有变化 调用callback let hasChange = prevDeps ? depsAry.every((dep, index) => dep === prevDeps[index]) === false : true; // 判断值是否有变化 if (hasChange) { callback(); } // 同步依赖值 prevDepsAry[effectIndex] = depsAry; effectIndex++; } }// -------------useReduce------------- function useReducer(reducer, initialState) { const [state, setState] = useState(initialState); function dispatch(action) { const newState = reducer(state, action); setState(newState); } return [state, dispatch]; }function reducer(state, action) { switch (action.type) { case "increment": return state + 1; case "decrement": return state - 1; default: return state; } } const [count, dispatch] = useReducer(reducer, 0); function render() { stateIndex = 0; effectIndex = 0; ReactDOM.render(, document.getElementById("root")); }

【useState,useEffect,useReduce手写实现】类似于antd的一些组件库的组件,经常需要绑定一些value值和onChange事件。可以封装一个通用方法
function useUpdateInput(initvalue) { const [value, setValue] = useState(initvalue); return { value, onChange: (e) => setValue(e.target.value), }; } const username = useUpdateInput("");

Lazy使用
const LazyComponent = React.lazy(() => import('./test.js'))export default function Index(){ return }function Test(){ return hello world } const LazyComponent =React.lazy(()=> new Promise((resolve)=>{ setTimeout(()=>{ resolve({ default: ()=> }) },2000) }))

react中lazy实现
function lazy(ctor){ return { $$typeof: REACT_LAZY_TYPE, _payload:{ _status: -1,//初始化状态 _result: ctor, }, _init:function(payload){ if(payload._status===-1){ /* 第一次执行会走这里*/ const ctor = payload._result; const thenable = ctor(); payload._status = Pending; payload._result = thenable; thenable.then((moduleObject)=>{ const defaultExport = moduleObject.default; resolved._status = Resolved; // 1 成功状态 resolved._result = defaultExport; /* defaultExport 为我们动态加载的组件本身*/ }) } if(payload._status === Resolved){ // 成功状态 return payload._result; } else {//第一次会抛出Promise异常给Suspense throw payload._result; } } } }

Suspense让数据获取库与 React 紧密整合。如果一个数据请求库实现了对 Suspense 的支持,那么,在 React 中使用 Suspense 将会是自然不过的事。
Suspense能够自由的展现,请求中的加载效果。能让视图加载有更主动的控制权。
Suspense能够让请求数据到渲染更流畅灵活,我们不用在componentDidMount请求数据,再次触发render,一切交给Suspense解决,一气呵成。

    推荐阅读