Skip to content

Commit e27d614

Browse files
committed
feat: optimizations: re-render only when necessary
(cherry picked from commit 85efc83)
1 parent f42480a commit e27d614

File tree

2 files changed

+26
-17
lines changed

2 files changed

+26
-17
lines changed

src/immutable/useElmish.spec.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,6 @@ function defaultUpdate(
7070
}
7171
}
7272

73-
// TODO: Tests mit callBase und defer
74-
7573
let componentModel: Model | undefined;
7674

7775
describe("useElmish", () => {

src/immutable/useElmish.ts

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable react-hooks/exhaustive-deps */
2-
import { castImmutable, freeze, produce, type Draft, type Immutable } from "immer";
2+
import { castImmutable, enablePatches, freeze, produce, type Draft, type Immutable } from "immer";
33
import { useCallback, useEffect, useRef, useState } from "react";
44
import { execCmd, logMessage } from "../Common";
55
import { getFakeOptionsOnce } from "../fakeOptions";
@@ -141,6 +141,8 @@ function useElmish<TProps, TModel, TMessage extends Message>({
141141
let initializedModel = model;
142142

143143
if (!initializedModel) {
144+
enablePatches();
145+
144146
const [initModel, ...initCommands] = fakeOptions?.model ? [fakeOptions.model] : init(props);
145147

146148
initializedModel = castImmutable(freeze(initModel, true));
@@ -189,16 +191,18 @@ function useElmish<TProps, TModel, TMessage extends Message>({
189191
const [defer, getDeferred] = createDefer<TMessage>();
190192
const callBase = createCallBase<TProps, TModel, TMessage>(nextMsg, currentModel, propsRef.current, { defer });
191193

192-
const [updatedModel, ...commands] = callUpdate(update, nextMsg, currentModel, propsRef.current, { defer, callBase });
194+
const [modified, updatedModel, ...commands] = callUpdate(update, nextMsg, currentModel, propsRef.current, {
195+
defer,
196+
callBase,
197+
});
193198

194199
const deferredCommands = getDeferred();
195200

196201
currentModel = updatedModel;
197202

198203
execCmd(dispatch, ...commands, ...deferredCommands);
199204

200-
// TODO: optimieren
201-
return true;
205+
return modified;
202206
}
203207
}
204208

@@ -208,19 +212,26 @@ function callUpdate<TProps, TModel, TMessage extends Message>(
208212
model: Immutable<TModel>,
209213
props: TProps,
210214
options: UpdateFunctionOptions<TProps, TModel, TMessage>,
211-
): [Immutable<TModel>, ...(Cmd<TMessage> | undefined)[]] {
215+
): [boolean, Immutable<TModel>, ...(Cmd<TMessage> | undefined)[]] {
212216
const commands: (Cmd<TMessage> | undefined)[] = [];
213-
const updatedModel = produce(model, (draft: Draft<TModel>) => {
214-
if (typeof update === "function") {
215-
commands.push(...update(draft, msg, props, options));
216-
217-
return;
218-
}
217+
let modified = false;
218+
const updatedModel = produce(
219+
model,
220+
(draft: Draft<TModel>) => {
221+
if (typeof update === "function") {
222+
commands.push(...update(draft, msg, props, options));
223+
224+
return;
225+
}
219226

220-
commands.push(...callUpdateMap(update, msg, draft, props, options));
221-
});
227+
commands.push(...callUpdateMap(update, msg, draft, props, options));
228+
},
229+
(patches) => {
230+
modified = patches.length > 0;
231+
},
232+
);
222233

223-
return [updatedModel, ...commands];
234+
return [modified, updatedModel, ...commands];
224235
}
225236

226237
function callUpdateMap<TProps, TModel, TMessage extends Message>(
@@ -237,4 +248,4 @@ function callUpdateMap<TProps, TModel, TMessage extends Message>(
237248

238249
export type { UseElmishOptions };
239250

240-
export { callUpdate, callUpdateMap, useElmish };
251+
export { callUpdateMap, useElmish };

0 commit comments

Comments
 (0)