hooks-useState
案例
function FunctionComponent(props) {
//
const [state, dispatch] = useState(1);
return (
<div className="border">
<p onClick={()=>{
dispatch(2);
}}>{props.name}{state}</p>
</div>
);
}
同理前面useReducer的流程,核心看useState的mount和update。
mountState
function mountState(initialState) {
var hook = mountWorkInProgressHook();
if (typeof initialState === 'function') {
initialState = initialState();
}
// 初始值给到hook链的memoizedState
hook.memoizedState = hook.baseState = initialState;
var queue = hook.queue = {
pending: null,
dispatch: null,
lastRenderedReducer: basicStateReducer,// 需要重点关注
lastRenderedState: initialState
};
// 初始化绑定,当前的fiber节点和合并链
var dispatch = queue.dispatch = dispatchAction.bind(null, currentlyRenderingFiber$1, queue);
return [hook.memoizedState, dispatch];
}
basicStateReducer
这个函数和后续更新有关系。初始化时只是绑定上了。
function basicStateReducer(state, action) {
return typeof action === 'function' ? action(state) : action;
}
dispatchAction
更新时的入口,和useReducer的dispatchAction时一摸一样的,只不过这里的话会有不同的解读。
fiber和quene时我们绑定时传入的参数,userState的 action 是我们在调用dispatch的时候传过来的函数或者其他数据。所以basicStateReducer得到的是函数就执行得到结果,是其他的数据直接返回。
function dispatchAction(fiber, queue, action) {
{
if (typeof arguments[3] === 'function') {
error("State updates from the useState() and useReducer() Hooks don't support the " + 'second callback argument. To execute a side effect after ' + 'rendering, declare it in the component body with useEffect().');
}
}
var eventTime = requestEventTime();
var lane = requestUpdateLane(fiber);
// update 循环链表,会存储state,合并state更新,也就是说我们在同一个地方多次设置state的值时,会在整个update扫描完毕之后再去做更新。
var update = {
lane: lane,
action: action,
eagerReducer: null,
eagerState: null,
next: null
}; // Append the update to the end of the list.
var pending = queue.pending;
if (pending === null) {
// This is the first update. Create a circular list.
update.next = update;
} else {
update.next = pending.next;
pending.next = update;
}
queue.pending = update;
var alternate = fiber.alternate;
if (fiber === currentlyRenderingFiber$1 || alternate !== null && alternate === currentlyRenderingFiber$1) {
didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true;
} else {
if (fiber.lanes === NoLanes && (alternate === null || alternate.lanes === NoLanes)) {
var lastRenderedReducer = queue.lastRenderedReducer;
if (lastRenderedReducer !== null) {
var prevDispatcher;
{
prevDispatcher = ReactCurrentDispatcher$1.current;
ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
}
try {
var currentState = queue.lastRenderedState;
// 这里额外处理
var eagerState = lastRenderedReducer(currentState, action); //
update.eagerReducer = lastRenderedReducer;
update.eagerState = eagerState;
if (objectIs(eagerState, currentState)) {
return;
}
} catch (error) {
} finally {
{
ReactCurrentDispatcher$1.current = prevDispatcher;
}
}
}
}
{
if ('undefined' !== typeof jest) {
warnIfNotScopedWithMatchingAct(fiber);
warnIfNotCurrentlyActingUpdatesInDev(fiber);
}
}
scheduleUpdateOnFiber(fiber, lane, eventTime);
}
}
updateState
更新走的是useReducer的逻辑,只不过是将basicStateReducer当作action传递给updateReducer,updateReducer中获取update的action,得到值
function updateState(initialState) {
return updateReducer(basicStateReducer);
}
写在最后
useState可以看作是一个useReducer,借用的userReducer去保存数据到fiber上。