react-deepwatch 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts ADDED
@@ -0,0 +1,218 @@
1
+ import { ReactNode } from "react";
2
+ import { PreserveOptions } from "./preserve";
3
+ type WatchedComponentOptions = {
4
+ /**
5
+ * A fallback react tree to show when some `load(...)` statement in <strong>this</strong> component is loading.
6
+ * Use this if you have issues with screen flickering with <code><Suspense></code>.
7
+ */
8
+ fallback?: ReactNode;
9
+ /**
10
+ * Wraps this component in a {@link https://react.dev/reference/react/memo memo} to prevent unnecessary re-renders.
11
+ * This is enabled by default, since watchedComponents smartly tracks deep changes of used props and knows when to rerender.
12
+ * Disable this only in a mixed scenario with non-watchedComponents, where they rely on the old way of fully re-rendering the whole tree to pass deep model data (=more than using shallow, primitive props) to the leaves. So this component does not block these re-renders in the middle.
13
+ * <p>
14
+ * Default: true
15
+ * </p>
16
+ */
17
+ memo?: boolean;
18
+ /**
19
+ * TODO
20
+ * Normally, everything that's **taken** from props, {@link useWatchedState} or {@link watched} or load(...)'s result will be returned, wrapped in a proxy that watches for modifications.
21
+ * So far, so good, this can handle all stuff that's happening inside your component, but the outside world does not have these proxies. For example, when a parent component is not a watchedComponent, and passed in an object (i.e. the model) into this component via props.
22
+ * Therefore this component can also **patch** these objects to make them watchable.
23
+ *
24
+ *
25
+ * <p>Default: true</p>
26
+ */
27
+ watchOutside?: boolean;
28
+ /**
29
+ * TODO: implement
30
+ * Preserves object instances in props by running the {@link preserve} function over the props (where the last value is memoized).
31
+ * <p>
32
+ * It's not recommended to enable this. Use only as a workaround when working with non-watched components where you have no control over. Better run {@link preserve} on the fetched source and keep a consistent-instance model in your app in the first place.
33
+ * </p>
34
+ *
35
+ * Note: Even with false, the `props` root object still keeps its instance (so it's save to watch `props.myFirstLevelProperty`).
36
+ * <p>
37
+ * Default: false
38
+ * </p>
39
+ */
40
+ preserveProps?: boolean;
41
+ };
42
+ export declare function watchedComponent<PROPS extends object>(componentFn: (props: PROPS) => any, options?: WatchedComponentOptions): ((props: PROPS) => any) | import("react").MemoExoticComponent<(props: PROPS) => any>;
43
+ type WatchedOptions = {
44
+ /**
45
+ * TODO: Implement
46
+ * Called, when a deep property was changed through the proxy.
47
+ */
48
+ onChange?: () => void;
49
+ /**
50
+ * TODO: Implement
51
+ * Called on a change to one of those properties, that were read-recorded in the component function (through the proxy of course).
52
+ * Reacts also on external changes / not done through the proxy.
53
+ */
54
+ onRecordedChange?: () => void;
55
+ };
56
+ export declare function useWatchedState(initial: object, options?: WatchedOptions): object;
57
+ type LoadOptions = {
58
+ /**
59
+ * For {@link LoadOptions#preserve preserving} the result's object identity.
60
+ * Normally, this is obtained from the call stack information plus the {@link LoadOptions#key}.
61
+ *
62
+ * @see LoadOptions#key
63
+ */
64
+ id?: string | number | object;
65
+ /**
66
+ * Helps identifying the load(...) call from inside a loop for {@link LoadOptions#preserve preserving} the result's object identity.
67
+ * @see LoadOptions#id
68
+ */
69
+ key?: string | number;
70
+ /**
71
+ * If you specify a fallback, the component can be immediately rendered during loading.
72
+ * <p>
73
+ * undefined = undefined as fallback.
74
+ * </p>
75
+ */
76
+ fallback?: unknown;
77
+ /**
78
+ * Performance: Will return the old value from a previous load, while this is still loading. This causes less disturbance (i.e. triggering dependent loads) while switching back to the fallback and then to a real value again.
79
+ * <p>Best used in combination with {@link isLoading} and {@link fallback}</p>
80
+ * <p>Default: false</p>
81
+ */
82
+ silent?: boolean;
83
+ /**
84
+ * Performance: Set to false, to mark following `load(...)` statements do not depend on the result. I.e when used only for immediate rendering or passed to child components only. I.e. <div>{load(...)}/div> or `<MySubComponent param={load(...)} />`:
85
+ * Therefore, the following `load(...)` statements may not need a reload and can run in parallel.
86
+ * <p>
87
+ * Default: true
88
+ * </p>
89
+ */
90
+ critical?: boolean;
91
+ /**
92
+ * Poll after this amount of milliseconds
93
+ */
94
+ poll?: number;
95
+ /**
96
+ * {@link isLoading} Can filter for only the load(...) statements with this given name.
97
+ */
98
+ name?: string;
99
+ /**
100
+ *
101
+ * <p>Default: true</p>
102
+ */
103
+ preserve?: boolean | PreserveOptions;
104
+ };
105
+ type PollOptions = {
106
+ /**
107
+ * Interval in milliseconds
108
+ */
109
+ interval: number;
110
+ /**
111
+ * - true = interval means loaderFn-start to loaderFn-start
112
+ * - false = interval means loaderFn-end to loaderFn-start (the longer loaderFn takes, the more time till next re-poll)
113
+ * <p>
114
+ * Default: true
115
+ * </p>
116
+ */
117
+ fixedInterval?: boolean;
118
+ };
119
+ /**
120
+ * Runs the async loaderFn and re-renders, if its promise was resolved. Also re-renders and re-runs loaderFn, when some of its watched dependencies, used prior or instantly in the loaderFn, change.
121
+ * Puts the component into suspense while loading. Throws an error when loaderFn throws an error or its promise is rejected. Resumes from react-error-boundary automatically when loaderFn was re-run(because of the above).
122
+ * <p>
123
+ * {@link https://github.com/bogeeee/react-deepwatch#and-less-loading-code Usage}.
124
+ * </p>
125
+ * @param loaderFn
126
+ * @param options
127
+ */
128
+ export declare function load<T, FALLBACK>(loaderFn: (oldResult?: T) => Promise<T>, options?: Omit<LoadOptions, "fallback">): T;
129
+ /**
130
+ * Runs the async loaderFn and re-renders, if its promise was resolved. Also re-renders and re-runs loaderFn, when some of its watched dependencies, used prior or instantly in the loaderFn, change.
131
+ * Puts the component into suspense while loading. Throws an error when loaderFn throws an error or its promise is rejected. Resumes from react-error-boundary automatically when loaderFn was re-run(because of the above).
132
+ * <p>
133
+ * {@link https://github.com/bogeeee/react-deepwatch#and-less-loading-code Usage}.
134
+ * </p>
135
+ * @param loaderFn
136
+ * @param options
137
+ */
138
+ export declare function load<T, FALLBACK>(loaderFn: (oldResult?: T) => Promise<T>, options: LoadOptions & {
139
+ fallback: FALLBACK;
140
+ }): T | FALLBACK;
141
+ /**
142
+ * Probe if a <code>load(...)</code> statement directly inside this watchedComponent is currently loading.
143
+ * Note: It's mostly needed to also specify a {@link LoadOptions#fallback} in the load statement's options to produce a valid render result while loading. Otherwise the whole component goes into suspense.
144
+ * <p>
145
+ * Example. This uses isLoading() to determine if the Dropdown list should be faded/transparent during while items are loading:
146
+ * <pre><code>
147
+ * return <select style={{opacity: isLoading("dropdownItems")?0.5:1}}>
148
+ * {load(() => fetchMyDropdownItems(), {name: "dropdownItems", fallback: ["loading items"]}).map(i => <option value="{i}">{i}</option>)}
149
+ * </select>
150
+ * </code></pre>
151
+ * </p>
152
+ * <p>
153
+ * Caveat: You must not use this for a condition that cuts away a load(...) statement in the middle of your render code. This is because an extra render run is issued for isLoading() and the load(...) statements are re-matched by their order.
154
+ * </p>
155
+ * @param nameFilter When set, consider only those with the given {@link LoadOptions#name}. I.e. <code>load(..., {name: "myDropdownListEntries"})</code>
156
+ *
157
+ */
158
+ export declare function isLoading(nameFilter?: string): boolean;
159
+ /**
160
+ * Probe if a <code>load(...)</code> statement directly inside this watchedComponent failed.
161
+ * <p>
162
+ * Example:
163
+ * <pre><code>
164
+ * if(loadFailed()) {
165
+ * return <div>Load failed: {loadFailed().message}</div>;
166
+ * }
167
+ *
168
+ * return <div>My component content {load(...)} </div>
169
+ * </code></pre>
170
+ * </p>
171
+ * <p>
172
+ * Caveat: You must not use this for a condition that cuts away a load(...) statement in the middle of your render code. This is because an extra render run is issued for loadFailed() and the load(...) statements are re-matched by their order.
173
+ * </p>
174
+ * @param nameFilter When set, consider only those with the given {@link LoadOptions#name}. I.e. <code>load(..., {name: "myDropdownListEntries"})</code>
175
+ * @returns unknown The thrown value of the loaderFn or undefined if everything is ok.
176
+ */
177
+ export declare function loadFailed(nameFilter?: string): unknown;
178
+ /**
179
+ * Like {@link load}, but re-runs loaderFn regularly at the interval, specified in the options.
180
+ * <p>
181
+ * Example: <code>return <div>The current outside temperature is { poll( async () => await fetchTemperatureFromServer(), {interval: 1000} ) }° </div></code> *
182
+ * </p>
183
+ * <p>
184
+ * Polling is still continued in recoverable error cases, when
185
+ * </p>
186
+ * - loaderFn fails but your watchedComponent catches it and returns fine.
187
+ * - Your watchedComponent returns with an error(because of this loaderFn or some other reason) and it is wrapped in a react-error-boundary.
188
+ *
189
+ * <p>
190
+ * Note, that after the initial load, re-polling is done <strong>very silently</strong>. Meaning, there's no suspense / fallback / isLoading indicator involved.
191
+ * </p>
192
+ * @param loaderFn
193
+ * @param options
194
+ */
195
+ export declare function poll<T, FALLBACK>(loaderFn: (oldResult?: T) => Promise<T>, options: Omit<LoadOptions, "fallback"> & PollOptions): T;
196
+ /**
197
+ * Like {@link load}, but re-runs loaderFn regularly at the interval, specified in the options.
198
+ * <p>
199
+ * Example: <code>return <div>The current outside temperature is { async poll( await () => fetchTemperatureFromServer(), {interval: 1000} ) }° </div></code> *
200
+ * </p>
201
+ * <p>
202
+ * Polling is still continued in recoverable error cases, when
203
+ * </p>
204
+ * - loaderFn fails but your watchedComponent catches it and returns fine.
205
+ * - Your watchedComponent returns with an error(because of this loaderFn or some other reason) and it is wrapped in a react-error-boundary.
206
+ *
207
+ * <p>
208
+ * Note, that after the initial load, re-polling is done <strong>very silently</strong>. Meaning, there's no suspense / fallback / isLoading indicator involved.
209
+ * </p>
210
+ * @param loaderFn
211
+ * @param options
212
+ */
213
+ export declare function poll<T, FALLBACK>(loaderFn: (oldResult?: T) => Promise<T>, options: LoadOptions & {
214
+ fallback: FALLBACK;
215
+ } & PollOptions): T | FALLBACK;
216
+ export declare function debug_tagComponent(name: string): void;
217
+ export {};
218
+ //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}