跳到主要内容

模拟实现

2023年06月11日
柏拉文
越努力,越幸运

一、实现


1.1 packages/react-reconciler/fiberHooks.js

function readContext(context) {
const consumer = currentlyRenderingFiber;
return readContextOrigin(consumer, context);
}

/**
* @description: Mount 阶段 Hooks 实现
*/
const HooksDispatcherOnMount = {
useRef: mountRef,
useState: mountState,
useEffect: mountEffect,
useContext: readContext,
useTransition: mountTransition
};

/**
* @description: Update 阶段 Hooks 实现
*/
const HooksDispatcherOnUpdate = {
useRef: updateRef,
useState: updateState,
useEffect: updateEffect,
useContext: readContext,
useTransition: updateTransition
};

1.2 /packages/react-reconciler/fiberContext.js

export function readContext(consumer, context) {
if (consumer == null) {
throw new Error('请在函数组件内调用 useContext');
}

const value = context._currentValue;

const contextItem = {
context,
next: null,
memoizedState: value
};

if (lastContextDep == null) {
lastContextDep = contextItem;
consumer.dependencies = {
lanes: NoLanes,
firstContext: contextItem
};
} else {
lastContextDep = lastContextDep.next = contextItem;
}

return value;
}

二、测试


<!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 useContext</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: { useState, useContext, useEffect, createContext, createElement }
} = React;

const context = createContext();

function Child() {
const ctx = useContext(context);
return createElement('div', null, ctx.a);
}

function App() {
const [value, setValue] = useState(0);

return createElement(
'div',
{
onClick: () => setValue(value + 1)
},
createElement(
context.Provider,
{ value: { a: value } },
createElement(Child)
)
);
}

const root = createRoot(document.getElementById('root'));
root.render(createElement(App));
</script>
</body>
</html>