实现自定义react hooks
作者:互联网
1:实现简版的 useState
每次调用顺序索引必须一样
返回初始状态变量,和更改状态方法
调用更改状态方法,更新状态并重新渲染
let lastStates = []
let index;
function useState(initValue) {
let state = lastStates[index] || initValue;
let currIndex = index;
let setState = (newState) => {
lastStates[currIndex] = newState;
render();
}
index++
return [state,setState]
}
2:实现简版的 useMemo
如果有dependencies未变化,返回上次对象的值
如果dependencies有变化,执行callback,返回新对象
let lastMemo
let lastMemoDependencies
function useMemo(callback,dependencies) {
if (!lastMemo) {
lastMemo = callback();
lastMemoDependencies = dependencies;
}
else {
let changed = !dependencies.every((item, idx) => item === lastMemoDependencies[idx])
if (changed) {
lastMemo = callback();
lastMemoDependencies = dependencies;
}
}
return lastMemo;
}
3:实现简版的 useCallback
如果有dependencies未变化,返回上次callback
如果dependencies有变化,返回新的callback
let lastCallback
let lastCallbackDependencies
function useCallback(callback,dependencies) {
if (!lastCallback) {
lastCallback = callback;
lastCallbackDependencies = dependencies;
}
else {
let changed = !dependencies.every((item, idx) => item === lastCallbackDependencies[idx])
if (changed) {
lastCallback = callback;
lastCallbackDependencies = dependencies;
}
}
return lastCallback;
}
4:实现简版的 useReducer
传入reducer,
返回状态和dispatch函数
let lastState
function useReducer(reducer, initValue) {
lastState=lastState || initValue;
let dispatch = function (action) {
lastState= reducer(lastState, action);
render();
}
return [lastState,dispatch]
}
5:实现简版的 useContext
共享变量
let Context = React.createContext();
function useContext(Context) {
console.log('Context',Context);
return Context._currentValue
}
此处Provider组件可以共享变量,useContext可以拿到对应的变量数据,在Counter组件中就可以使用useContext获取变量
<Context.Provider value={{ state, setState }}>
<Counter></Counter>
</Context.Provider>
6:实现简版的 useEffect
浏览器事件环:
1)执行脚本代码(宏任务队列中取出)
2)进入主执行栈,依次执行
3)如遇到setTimeout,ajax,event, 把对应的回调放入宏任务队列, 宏任务队列在页面渲染之后执行
4)如遇到Promise, 把对应的回调放入微任务队列, 在页面渲染之前执行,所以任务会阻碍页面的渲染
5)显示器刷新率是60HZ, 每秒钟刷新60次, 也是就是16.67毫秒刷新一次
//在浏览器渲染后执行,不会阻塞浏览器运行
let lastDependencies
function useEffect(callback,dependencies) {
if (!lastDependencies) {
lastDependencies = dependencies;
setTimeout(() => {
callback();
}, 0);
}
else {
let changed = !dependencies.every((item, idx) => item === lastDependencies[idx])
if (changed) {
lastDependencies = dependencies;
callback();
}
}
}
//在浏览器渲染前执行,会阻塞浏览器运行
let lastLayOutDependencies
function useLayoutEffect(callback,dependencies) {
if (!lastLayOutDependencies) {
lastLayOutDependencies = dependencies;
queueMicrotask(callback);
// Promise.resolve().then(callback)
}
else {
let changed = !dependencies.every((item, idx) => item === lastLayOutDependencies[idx])
if (changed) {
lastLayOutDependencies = dependencies;
queueMicrotask(callback);
// Promise.resolve().then(callback)
}
}
}
<!DOCTYPE html>
<html lang="en">
<script>
// display Hello World and then page stuck because the infinite loop
setTimeout(() => {
while (true) {}
console.log('setTimeout');
document.body.style.backgroundColor = '#ccc';
}, 0);
// no Hello World display and page stuck because the infinite loop
Promise.resolve().then(() => {
while (true) {}
console.log('Promise');
});
</script>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
Hello World
</body>
</html>
标签:idx,自定义,item,hooks,changed,react,callback,dependencies,let 来源: https://www.cnblogs.com/dming4/p/16519782.html