How to use mountWorkInProgressHook method in Playwright Internal

Best JavaScript code snippet using playwright-internal

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

hook.js

Source: hook.js Github

copy
1mount阶段: //scheduleUpdateOnFiber
2  我们需要初始化状态,并返回修改状态的方法。
3  我们要区分管理每个Hooks。
4  提供一个数据结构去存放更新逻辑,以便后续每次更新可以拿到最新的值。
5
6const [num, setNum] = useState(0)
7const [num1, setNum1] = useState(100)
8
9
10function mountState (initialState) {
11  // 获取当前的Hook节点,同时将当前Hook添加到Hook链表中
12  const hook = mountWorkInProgressHook();
13  if (typeof initialState === 'function') {
14    initialState = initialState();
15  }
16  hook.memoizedState = hook.baseState = initialState;
17  // 声明一个链表来存放更新
18  const queue = (hook.queue = {
19    last: null,
20    dispatch: null,
21    lastRenderedReducer,
22    lastRenderedState,
23  });
24  // 返回一个dispatch方法用来修改状态,并将此次更新添加update链表中
25  const dispatch = (queue.dispatch = (dispatchAction.bind(
26    null,
27    currentlyRenderingFiber,
28    queue,
29  )));
30  // 返回当前状态和修改状态的方法 
31  return [hook.memoizedState, dispatch];
32}
33
34
35function mountWorkInProgressHook(): Hook {
36  const hook: Hook = {
37    memoizedState: null,
38    baseState: null,
39    queue: null,
40    baseUpdate: null,
41    next: null,
42  };
43  if (workInProgressHook === null) {
44    // 当前workInProgressHook链表为空的话,
45    // 将当前Hook作为第一个Hook
46    firstWorkInProgressHook = workInProgressHook = hook;
47  } else {
48    // 否则将当前Hook添加到Hook链表的末尾
49    workInProgressHook = workInProgressHook.next = hook;
50  }
51  return workInProgressHook;
52}
53
54function dispatchAction(fiber,queue,action,) {
55    const update = {
56      action,
57      next: null,
58    };
59    // 将update对象添加到循环链表中
60    const last = queue.last;
61    if (last === null) {
62      // 链表为空,将当前更新作为第一个,并保持循环
63      update.next = update;
64    } else {
65      const first = last.next;
66      if (first !== null) {
67        // 在最新的update对象后面插入新的update对象
68        update.next = first;
69      }
70      last.next = update;
71    }
72    // 将表头保持在最新的update对象上
73    queue.last = update;
74   // 进行调度工作
75    scheduleWork();
76}
77
78
79
80mountWorkInProgressHook ==>
81{
82  baseQueue: null,
83  baseState: 0,
84  memoizedState: 0,
85  next: {
86    memoizedState: 100,
87    baseState: 100, 
88    baseQueue: null, 
89    queue: {
90      dispatch: ƒ (),
91      lastRenderedReducer: ƒ basicStateReducer(state, action),
92      lastRenderedState: 100,
93      pending: null,
94    }
95  },
96  queue: {
97    dispatch: ƒ (),
98    lastRenderedReducer: ƒ basicStateReducer(state, action),
99    lastRenderedState: 0,
100    pending: null,
101  }
102}
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
Full Screen

useState&usereducer.js

Source: useState&usereducer.js Github

copy
1
2
3//########1.声明阶段
4
5/***********mount时************/ 
6//useState的执行方法
7function mountState<S>(
8    initialState: (()=>S) | S,
9) : [S, Dispatch<BasicStateAction<S>>]{
10    //创建并返回当前的hook
11    const hook = mountWorkInProgressHook()
12
13    //...复制初始化state
14
15
16    //创建queue
17    const queue = (hook.queue = {
18        pending: null,
19        dispatch: null,
20        //这里的basicStateReducer为useReducer的一个方法,下文可见
21        lastRenderedReducer: basicStateReducer,
22        lastRenderedState: (initialState: any),
23    })
24
25
26    //...创建dispatch
27    return [hook.memoizedState, dispatch]
28}
29
30
31function mountreducer<S, I, A>(
32    reducer:(S, A) => S,
33    initialArg: I,
34    init?: I=>S,
35):[S,Dispatch<A>]{
36    //创建并返回当前的hook
37    const hook = mountWorkInProgressHook()
38
39
40    //...复制初始state
41
42    //创建queue
43    const queu = (hook.queue = {
44        //保存update对象
45        pending: null,
46
47        //保存dispatchAction.bind()的值
48        dispatch: null,
49
50        //上一次render时使用的reducer
51        lastRenderedReducer: reducer,
52
53        //上一次render时的state
54        lastRenderedState: (initialState: any)
55    })
56
57
58    //...创建dispatch
59    return [hook.memoizedState, dispatch];
60}
61
62
63function basicStateReducer<S>(state:S, action:BasicStateAction<S>):S{
64    //这里对应这 useState的函数式更新和普通的赋值更新
65    return typeof action === 'function' ? action(state) : action
66}
67
68
69/***********update时************/ 
70//更新时,两者调用的是同一个函数updateReducer
71
72function updateReducer<S, I, A>(
73    reducer:(S, A) => S,
74    initialAtg:I,
75    init?: I => S,
76):[S, Dispatch<A>]{
77    //获取当前的hooks
78    const hook = updateWorkInProgressHook()
79    const queue = hook.queue
80
81    queue.lastRenderedReducer = reducer
82
83    //..同update与updateQueue类似的更新逻辑
84
85    const dispatch: Dispatch<A> = (queue.dispatch: any);
86    return [hook.memoizedState, dispatch]
87}
88
89
90
91//########2.调用阶段
92
93function dispatchAction(fiber, queue, action){
94
95    //...创建update
96    const update = {
97        eventTime: eventTime,
98        lane:lane,
99        suspenseConfig:suspenseConfig,
100        action:action,
101        eagerReducer:null,
102        eagerState:null,
103        next:null,
104    }
105
106
107    //...将update加入到queue.pending
108
109    let alternate = fiber.alternate
110    if(
111        //currentlyRenderingFiber即workInProgress 
112        //workInProgress存在代表当前处于render阶段。
113        fiber === currentlyRenderingFiber$1 ||
114        alternate !== null &&
115        alternate === currentlyRenderingFiber$1
116        ){
117        //render阶段触发的更新 做一个标记
118        didScheduleRenderPhaseUpdateDuringThisPass = 
119        disScheduleRenderPhaseUpdate = true
120        } else {
121            //判断优先级
122            if(
123                fiber.lanes === NoLanes &&
124                (alternate === null || alternate.lanes === NoLanes)
125                ){
126                    ///...fiber的updateQueue为空,优化路径
127                }
128
129
130                scheduleUpdateOnFiber(fiber, lane, eventTime);
131        }
132}
133//总的流程概括就是,创建update,将其加入到queu.pending中,并开启调度
134
135
136
137//传入给useReducer的reducer函数其实是可变的
138import { StrictMode, useReducer } from "react";
139import ReactDOM from "react-dom";
140
141const currentReducerRef = {
142  current: null
143};
144
145const addReducer = (state) => state + 1;
146const subReducer = (state) => state - 1;
147let i = 0;
148
149setInterval(() => {
150  currentReducerRef.current = i++ % 2 ? addReducer : subReducer;
151}, 1000);
152
153function App() {
154  const [state, dispatch] = useReducer(currentReducerRef.current, 0);
155
156  return <button onClick={dispatch}>数字是:{state}</button>;
157}
158
159const rootElement = document.getElementById("root");
160ReactDOM.render(
161  <StrictMode>
162    <App />
163  </StrictMode>,
164  rootElement
165);
166
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Playwright Internal on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)