Match-id-2c5aabb8936793c38d7908e5b5a9c1126c5799ed

This commit is contained in:
* 2022-08-05 17:13:54 +08:00 committed by *
commit 42d3046281
4 changed files with 74 additions and 48 deletions

View File

@ -1,38 +1,34 @@
module.exports = { module.exports = {
presets: [ presets: ['@babel/preset-typescript', ['@babel/preset-env', { targets: { node: 'current' } }]],
'@babel/react',
'@babel/preset-typescript',
['@babel/preset-env', { targets: { node: 'current' } }]
],
plugins: [ plugins: [
['@babel/plugin-proposal-class-properties', { loose: true }], '@babel/plugin-syntax-jsx',
[ [
'@babel/plugin-proposal-object-rest-spread', '@babel/plugin-transform-react-jsx',
{ loose: true, useBuiltIns: true }, {
pragma: 'Horizon.createElement',
pragmaFrag: 'Horizon.Fragment',
},
], ],
['@babel/plugin-transform-template-literals', { loose: true }], ['@babel/plugin-proposal-class-properties', { loose: true }],
['@babel/plugin-proposal-private-methods', { loose: true }],
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
'@babel/plugin-transform-object-assign', '@babel/plugin-transform-object-assign',
'@babel/plugin-transform-literals',
'@babel/plugin-transform-arrow-functions',
'@babel/plugin-transform-block-scoped-functions',
'@babel/plugin-transform-object-super', '@babel/plugin-transform-object-super',
['@babel/plugin-proposal-object-rest-spread', { loose: true, useBuiltIns: true }],
['@babel/plugin-transform-template-literals', { loose: true }],
'@babel/plugin-transform-arrow-functions',
'@babel/plugin-transform-literals',
'@babel/plugin-transform-for-of',
'@babel/plugin-transform-block-scoped-functions',
'@babel/plugin-transform-classes',
'@babel/plugin-transform-shorthand-properties', '@babel/plugin-transform-shorthand-properties',
'@babel/plugin-transform-computed-properties', '@babel/plugin-transform-computed-properties',
'@babel/plugin-transform-for-of',
['@babel/plugin-transform-spread', { loose: true, useBuiltIns: true }],
'@babel/plugin-transform-parameters', '@babel/plugin-transform-parameters',
['@babel/plugin-transform-destructuring', { loose: true, useBuiltIns: true }], ['@babel/plugin-transform-spread', { loose: true, useBuiltIns: true }],
['@babel/plugin-transform-block-scoping', { throwIfClosureRequired: false }], ['@babel/plugin-transform-block-scoping', { throwIfClosureRequired: false }],
'@babel/plugin-transform-classes', ['@babel/plugin-transform-destructuring', { loose: true, useBuiltIns: true }],
'@babel/plugin-transform-runtime', '@babel/plugin-transform-runtime',
'@babel/plugin-proposal-nullish-coalescing-operator', '@babel/plugin-proposal-nullish-coalescing-operator',
'@babel/plugin-proposal-optional-chaining', '@babel/plugin-proposal-optional-chaining',
['@babel/plugin-proposal-private-methods', { 'loose': true }],
['@babel/plugin-proposal-private-property-in-object', { 'loose': true }],
'@babel/plugin-syntax-jsx',
['@babel/plugin-transform-react-jsx', {
pragma: 'Horizon.createElement',
pragmaFrag: 'Horizon.Fragment'
}],
], ],
}; };

View File

@ -1,20 +1,18 @@
import type { Hook, Reducer, Trigger, Update } from './HookType'; import type { Hook, Reducer, Trigger, Update } from './HookType';
import { import { createHook, getCurrentHook, throwNotInFuncError } from './BaseHook';
createHook, import { launchUpdateFromVNode } from '../TreeBuilder';
getCurrentHook,
throwNotInFuncError
} from './BaseHook';
import {
launchUpdateFromVNode
} from '../TreeBuilder';
import { isSame } from '../utils/compare'; import { isSame } from '../utils/compare';
import { setStateChange } from '../render/FunctionComponent'; import { setStateChange } from '../render/FunctionComponent';
import { getHookStage, HookStage } from './HookStage'; import { getHookStage, HookStage } from './HookStage';
import type { VNode } from '../Types'; import type { VNode } from '../Types';
import {getProcessingVNode} from '../GlobalVar'; import { getProcessingVNode } from '../GlobalVar';
export function useReducerImpl<S, P, A>(reducer: (S, A) => export function useReducerImpl<S, P, A>(
S, initArg: P, init?: (P) => S, isUseState?: boolean): [S, Trigger<A>] | void { reducer: (S, A) => S,
initArg: P,
init?: (P) => S,
isUseState?: boolean
): [S, Trigger<A>] | void {
const stage = getHookStage(); const stage = getHookStage();
if (stage === null) { if (stage === null) {
throwNotInFuncError(); throwNotInFuncError();
@ -53,16 +51,19 @@ function insertUpdate<S, A>(action: A, hook: Hook<S, A>): Update<S, A> {
} }
// setState, setReducer触发函数 // setState, setReducer触发函数
export function TriggerAction<S, A, T>(vNode: VNode, hook: Hook<S, A>, action: A) { export function TriggerAction<S, A>(vNode: VNode, hook: Hook<S, A>, isUseState: boolean, action: A): void {
const newUpdate = insertUpdate(action, hook); const newUpdate = insertUpdate(action, hook);
// 判断是否需要刷新 // 判断是否需要刷新
if (!vNode.shouldUpdate) { if (!vNode.shouldUpdate && isUseState) {
const reducerObj = hook.state as Reducer<S, A>; const { stateValue, reducer } = hook.state as Reducer<S, A>;
const { stateValue, reducer } = reducerObj;
if (reducer === null) {
return;
}
// 在进入render阶段前reducer没有变化可以复用state值提升性能 // 在进入render阶段前reducer没有变化可以复用state值提升性能
newUpdate.state = reducer(stateValue, action); newUpdate.state = reducer(stateValue, action);
// 标记为已经计算过,不需要重新计算了 // 标记为已经计算过,不需要重新计算了
newUpdate.didCalculated = true; newUpdate.didCalculated = true;
@ -87,16 +88,17 @@ export function useReducerForInit<S, A>(reducer, initArg, init, isUseState?: boo
} }
const hook = createHook(); const hook = createHook();
const trigger = TriggerAction.bind(null, getProcessingVNode(), hook, isUseState);
// 为hook.state赋值{状态值, 触发函数, reducer, updates更新数组, 是否是useState} // 为hook.state赋值{状态值, 触发函数, reducer, updates更新数组, 是否是useState}
hook.state = { hook.state = {
stateValue: stateValue, stateValue: stateValue,
trigger: TriggerAction.bind(null, getProcessingVNode(), hook), trigger,
reducer, reducer,
updates: null, updates: null,
isUseState isUseState,
} as Reducer<S, A>; } as Reducer<S, A>;
return [hook.state.stateValue, hook.state.trigger]; return [hook.state.stateValue, trigger];
} }
// 更新hook.state // 更新hook.state
@ -136,5 +138,3 @@ function calculateNewState<S, A>(currentHookUpdates: Array<Update<S, A>>, curren
return state; return state;
} }

View File

@ -33,12 +33,12 @@
"@babel/plugin-transform-object-assign": "7.16.7", "@babel/plugin-transform-object-assign": "7.16.7",
"@babel/plugin-transform-object-super": "7.16.7", "@babel/plugin-transform-object-super": "7.16.7",
"@babel/plugin-transform-parameters": "7.16.7", "@babel/plugin-transform-parameters": "7.16.7",
"@babel/plugin-transform-react-jsx": "7.16.7",
"@babel/plugin-transform-runtime": "7.16.7", "@babel/plugin-transform-runtime": "7.16.7",
"@babel/plugin-transform-shorthand-properties": "7.16.7", "@babel/plugin-transform-shorthand-properties": "7.16.7",
"@babel/plugin-transform-spread": "7.16.7", "@babel/plugin-transform-spread": "7.16.7",
"@babel/plugin-transform-template-literals": "7.16.7", "@babel/plugin-transform-template-literals": "7.16.7",
"@babel/preset-env": "7.16.7", "@babel/preset-env": "7.16.7",
"@babel/preset-react": "7.16.7",
"@babel/preset-typescript": "7.16.7", "@babel/preset-typescript": "7.16.7",
"@rollup/plugin-babel": "^5.3.1", "@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-node-resolve": "^13.3.0", "@rollup/plugin-node-resolve": "^13.3.0",

View File

@ -13,25 +13,25 @@ describe('useReducer Hook Test', () => {
return { return {
...intlCar, ...intlCar,
logo: 'ford', logo: 'ford',
price: 76 price: 76,
}; };
case 'bmw': case 'bmw':
return { return {
...intlCar, ...intlCar,
logo: 'bmw', logo: 'bmw',
price: 100 price: 100,
}; };
case 'benz': case 'benz':
return { return {
...intlCar, ...intlCar,
logo: 'benz', logo: 'benz',
price: 80 price: 80,
}; };
default: default:
return { return {
...intlCar, ...intlCar,
logo: 'audi', logo: 'audi',
price: 88 price: 88,
}; };
} }
}; };
@ -56,4 +56,34 @@ describe('useReducer Hook Test', () => {
expect(container.querySelector('p').innerHTML).toBe('audi'); expect(container.querySelector('p').innerHTML).toBe('audi');
expect(container.querySelector('#senP').innerHTML).toBe('88'); expect(container.querySelector('#senP').innerHTML).toBe('88');
}); });
it('dispatch只触发一次', () => {
let nextId = 1;
const reducer = () => {
return { data: nextId++ };
};
const btnRef = Horizon.createRef();
const Main = () => {
const [{ data }, dispatch] = useReducer(reducer, { data: 0 });
const dispatchLogging = () => {
console.log('dispatch is called once');
dispatch();
};
return (
<div>
<button ref={btnRef} onClick={() => dispatchLogging()}>
increment
</button>
<div>{data}</div>
</div>
);
};
Horizon.render(<Main />, container);
Horizon.act(() => {
btnRef.current.click();
});
expect(nextId).toBe(2);
});
}); });