模拟实现
2023年06月11日
一、认识
1.1 /packages/react/index.js
export const useMemo = (nextCreate, deps) => {
const dispatcher = resolveDispatcher();
return dispatcher.useMemo(nextCreate, deps);
};
1.2 /packages/react-reconciler/fiberHooks.js
function mountMemo(nextCreate, deps) {
const hook = mountWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
const nextValue = nextCreate();
hook.memoizedState = [nextValue, nextDeps];
return nextValue;
}
function updateMemo(nextCreate, deps) {
const hook = updateWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
const prevState = hook.memoizedState;
if (nextDeps !== null) {
const prevDeps = prevState[1];
if (areHookInputsEqual(nextDeps, prevDeps)) {
return prevState[0];
}
}
const nextValue = nextCreate();
hook.memoizedState = [nextValue, nextDeps];
return nextValue;
}
/**
* @description: Mount 阶段 Hooks 实现
*/
const HooksDispatcherOnMount = {
use,
useRef: mountRef,
useMemo: mountMemo,
useState: mountState,
useEffect: mountEffect,
useContext: readContext,
useCallback: mountCallback,
useTransition: mountTransition
};
/**
* @description: Update 阶段 Hooks 实现
*/
const HooksDispatcherOnUpdate = {
use,
useRef: updateRef,
useMemo: updateMemo,
useState: updateState,
useEffect: updateEffect,
useContext: readContext,
useCallback: updateCallback,
useTransition: updateTransition
};
二、测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React Mini KaSong useMemo</title>
<script>
var process = {
env: {
NODE_ENV: 'development'
}
};
</script>
<script src="../dist/react.iife.js"></script>
</head>
<body>
<div id="root"></div>
<script>
const {
ReactDOM: { createRoot },
React: { memo, useState, useMemo, createElement }
} = React;
function Cpn(props) {
const { uuid } = props;
console.log('Cpn Render', props);
return createElement('div', {}, 'Cpn');
}
const MemoCpn = memo(Cpn);
function getUniqueIdByNanoID(size = 10) {
let id = '';
let i = size;
const urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';
while (i--) {
id += urlAlphabet[(Math.random() * 64) | 0];
}
return id;
}
function getUniqueId(size) {
return getUniqueIdByNanoID(size);
}
function App() {
const [num, setNum] = useState(0);
console.log('App Render');
const uuid = getUniqueId();
// const uuid = useMemo(() => getUniqueId(), []);
return createElement('div', { onClick: () => setNum(num + 1) }, [
createElement(MemoCpn, { uuid })
]);
}
const root = createRoot(document.getElementById('root'));
root.render(createElement(App));
</script>
</body>
</html>