「05」实现状态更新机制

118 阅读2分钟

前面我们已经实现了Reconciler的架构,并且实现了renderRootrenderRoot会执行更新的过程,所以我们推测调用renderRoot的是那些触发更新的API,那么在React中常见的触发更新的API如下:

  • 对于首屏渲染来说是ReactDOM.createRoot(),老版本的是ReactDOM.render
  • 对于类组件是this.setState
  • 对于函数组件是useState的dispatch方法

明确目标

目前我们希望实现一套统一的更新机制,即兼容上述触发更新的方式,并且方便后续扩展,从当前的同步更新变成后续的并发更新,因为React18是并发更新。

这种更新机制的组成部分

  • Update代表更新的数据结构
  • UpdateQueue消费update的数据结构

从图中可以看到,一个UpdateQueue中有一个shared.pending,它指向update,如果我们有一个初始的状态,再消费这个update就得到了一个新的状态

实现Update基础结构

新建packages/react-reconciler/src/updateQueue.ts

实现Update接口
其中action需要兼容可能是function新的值,即对应的this.setState({})this.setState(()=>xxx)

export interface Update<State>{
    action:Action<State>
}
// ReactTypes.ts
export type Action<State> = State | ((prevState: State)=>State)

实现创建Update的方法createUpdate返回一个Update的实例

export const createUpdate = <State>(action: Action<State>) => {
	return {
		action
	};
};

实现UpdateQueue接口

export interface UpdateQueue<State> {
	shared: {
		pending: Update<State> | null;
	};
}

实现创建UpdateQueue的方法createUpdateQueue

export const createUpdateQueue = <Action>() => {
	return {
		shared: {
			pending: null
		}
	} as UpdateQueue<Action>;
};

实现往UpdateQueue中增加Update的方法enqueueUpdate

// 往updateQueue中添加update
export const enqueueUpdate = <Action>(
	updateQueue: UpdateQueue<Action>,
	update: Update<Action>
) => {
	updateQueue.shared.pending = update;
};

实现UpdateQueue消费Update的方法processUpdateQueue

接受一个初始的状态以及我们需要消费的update,返回值是一个全新的状态,首先使用初始状态来初始化返回值,之后判断action是传入的全新的值还是函数,在进行赋值

export const processUpdateQueue = <State>(
	baseState: State,
	pendingUpdate: Update<State> | null
): { memoizedState: State } => {
	const result: ReturnType<typeof processUpdateQueue<State>> = {
		memoizedState: baseState
	};

	if (pendingUpdate !== null) {
		// baseState 1   update 2 -> memoizedState 2
		// baseState 1   update (x)=>4x  ->  memoizedState 4
		const action = pendingUpdate.action;
		if (action instanceof Function) {
			result.memoizedState = action(baseState);
		} else {
			result.memoizedState = action;
		}
	}
	return result;
};

所有代码:github.com/ohlyf/oh-re…