// ----------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 = 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(<App />, document.getElementById("root"));}
相似于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 <Suspense fallback={<div>loading...</div>} > <LazyComponent /> </Suspense>}function Test(){ return <div className="demo" >hello world</div>}const LazyComponent = React.lazy(()=> new Promise((resolve)=>{ setTimeout(()=>{ resolve({ default: ()=> <Test /> }) },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解决,零打碎敲。