From 29dde34113ce5e145e881085531d98352646cbb8 Mon Sep 17 00:00:00 2001 From: * <8> Date: Thu, 4 Aug 2022 11:39:13 +0800 Subject: [PATCH 1/3] Match-id-733bd6158be43d7d7436252a34424b3e90d287e7 --- babel.config.js | 42 +++++++++++++++++++----------------------- package.json | 1 - 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/babel.config.js b/babel.config.js index 9f82d978..dd703552 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,38 +1,34 @@ module.exports = { - presets: [ - '@babel/react', - '@babel/preset-typescript', - ['@babel/preset-env', { targets: { node: 'current' } }] - ], + presets: ['@babel/preset-typescript', ['@babel/preset-env', { targets: { node: 'current' } }]], plugins: [ - ['@babel/plugin-proposal-class-properties', { loose: true }], + '@babel/plugin-syntax-jsx', [ - '@babel/plugin-proposal-object-rest-spread', - { loose: true, useBuiltIns: true }, + '@babel/plugin-transform-react-jsx', + { + 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-literals', - '@babel/plugin-transform-arrow-functions', - '@babel/plugin-transform-block-scoped-functions', '@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-computed-properties', - '@babel/plugin-transform-for-of', - ['@babel/plugin-transform-spread', { loose: true, useBuiltIns: true }], '@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-classes', + ['@babel/plugin-transform-destructuring', { loose: true, useBuiltIns: true }], '@babel/plugin-transform-runtime', '@babel/plugin-proposal-nullish-coalescing-operator', '@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' - }], ], }; diff --git a/package.json b/package.json index fe9836de..00137de2 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "@babel/plugin-transform-spread": "7.16.7", "@babel/plugin-transform-template-literals": "7.16.7", "@babel/preset-env": "7.16.7", - "@babel/preset-react": "7.16.7", "@babel/preset-typescript": "7.16.7", "@rollup/plugin-babel": "^5.3.1", "@rollup/plugin-node-resolve": "^13.3.0", From ac98a113818eb3df9052012ac3dd5bb6f3505291 Mon Sep 17 00:00:00 2001 From: * <8> Date: Thu, 4 Aug 2022 11:48:15 +0800 Subject: [PATCH 2/3] Match-id-7a6d0c76c028315336ef04338ffa315c8bc8c18e --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 00137de2..fe76b6b7 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@babel/plugin-transform-object-assign": "7.16.7", "@babel/plugin-transform-object-super": "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-shorthand-properties": "7.16.7", "@babel/plugin-transform-spread": "7.16.7", From e275c108dc5af5a6d798cfa8cde358cd91826b05 Mon Sep 17 00:00:00 2001 From: * <8> Date: Fri, 5 Aug 2022 16:38:13 +0800 Subject: [PATCH 3/3] Match-id-2d85e7b702d4272d993947bdb2536d54112a3111 --- .../src/renderer/hooks/UseReducerHook.ts | 40 +++++++++---------- .../ComponentTest/HookTest/UseReducer.test.js | 38 ++++++++++++++++-- 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/libs/horizon/src/renderer/hooks/UseReducerHook.ts b/libs/horizon/src/renderer/hooks/UseReducerHook.ts index c40da904..9dd38319 100644 --- a/libs/horizon/src/renderer/hooks/UseReducerHook.ts +++ b/libs/horizon/src/renderer/hooks/UseReducerHook.ts @@ -1,20 +1,18 @@ import type { Hook, Reducer, Trigger, Update } from './HookType'; -import { - createHook, - getCurrentHook, - throwNotInFuncError -} from './BaseHook'; -import { - launchUpdateFromVNode -} from '../TreeBuilder'; +import { createHook, getCurrentHook, throwNotInFuncError } from './BaseHook'; +import { launchUpdateFromVNode } from '../TreeBuilder'; import { isSame } from '../utils/compare'; import { setStateChange } from '../render/FunctionComponent'; import { getHookStage, HookStage } from './HookStage'; import type { VNode } from '../Types'; -import {getProcessingVNode} from '../GlobalVar'; +import { getProcessingVNode } from '../GlobalVar'; -export function useReducerImpl(reducer: (S, A) => - S, initArg: P, init?: (P) => S, isUseState?: boolean): [S, Trigger] | void { +export function useReducerImpl( + reducer: (S, A) => S, + initArg: P, + init?: (P) => S, + isUseState?: boolean +): [S, Trigger] | void { const stage = getHookStage(); if (stage === null) { throwNotInFuncError(); @@ -53,16 +51,19 @@ function insertUpdate(action: A, hook: Hook): Update { } // setState, setReducer触发函数 -export function TriggerAction(vNode: VNode, hook: Hook, action: A) { +export function TriggerAction(vNode: VNode, hook: Hook, isUseState: boolean, action: A): void { const newUpdate = insertUpdate(action, hook); // 判断是否需要刷新 - if (!vNode.shouldUpdate) { - const reducerObj = hook.state as Reducer; - const { stateValue, reducer } = reducerObj; + if (!vNode.shouldUpdate && isUseState) { + const { stateValue, reducer } = hook.state as Reducer; + if (reducer === null) { + return; + } // 在进入render阶段前reducer没有变化,可以复用state值,提升性能 newUpdate.state = reducer(stateValue, action); + // 标记为已经计算过,不需要重新计算了 newUpdate.didCalculated = true; @@ -87,16 +88,17 @@ export function useReducerForInit(reducer, initArg, init, isUseState?: boo } const hook = createHook(); + const trigger = TriggerAction.bind(null, getProcessingVNode(), hook, isUseState); // 为hook.state赋值{状态值, 触发函数, reducer, updates更新数组, 是否是useState} hook.state = { stateValue: stateValue, - trigger: TriggerAction.bind(null, getProcessingVNode(), hook), + trigger, reducer, updates: null, - isUseState + isUseState, } as Reducer; - return [hook.state.stateValue, hook.state.trigger]; + return [hook.state.stateValue, trigger]; } // 更新hook.state @@ -136,5 +138,3 @@ function calculateNewState(currentHookUpdates: Array>, curren return state; } - - diff --git a/scripts/__tests__/ComponentTest/HookTest/UseReducer.test.js b/scripts/__tests__/ComponentTest/HookTest/UseReducer.test.js index 5923d9ad..5e7f0876 100644 --- a/scripts/__tests__/ComponentTest/HookTest/UseReducer.test.js +++ b/scripts/__tests__/ComponentTest/HookTest/UseReducer.test.js @@ -13,25 +13,25 @@ describe('useReducer Hook Test', () => { return { ...intlCar, logo: 'ford', - price: 76 + price: 76, }; case 'bmw': return { ...intlCar, logo: 'bmw', - price: 100 + price: 100, }; case 'benz': return { ...intlCar, logo: 'benz', - price: 80 + price: 80, }; default: return { ...intlCar, logo: 'audi', - price: 88 + price: 88, }; } }; @@ -56,4 +56,34 @@ describe('useReducer Hook Test', () => { expect(container.querySelector('p').innerHTML).toBe('audi'); 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 ( +
+ +
{data}
+
+ ); + }; + + Horizon.render(
, container); + Horizon.act(() => { + btnRef.current.click(); + }); + expect(nextId).toBe(2); + }); });