Skip to content

Commit c83f55d

Browse files
committed
feat(error): 改善错误里
1 parent c52f91d commit c83f55d

File tree

10 files changed

+73
-42
lines changed

10 files changed

+73
-42
lines changed

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@ export default function () {
4242
# detail
4343

4444
```typescript
45-
import { createStore, useStore, Config } from "react-vue-state";
45+
import { createStore, useStore, useFunc, Config } from "react-vue-state";
4646

4747
/**
4848
* Override global error handling
4949
* error: specific error message
5050
* funcName: The name of the function where the error occurred
5151
* kind: Errors that occur in computed, methods, watch, setData
5252
*/
53-
Config.onError = (error: any, funcName: string, kind: string) => {
54-
console.log(kind, funcName, error);
53+
Config.onError = (error: any) => {
54+
console.log(kind);
5555
// do something
5656
};
5757

@@ -140,6 +140,14 @@ export default function () {
140140
setData,
141141
} = useStore(store);
142142

143+
/**
144+
* Any function may generate an error at runtime
145+
* "useFunc" can not only catch errors but also ensure that the address of the component will not change after ReRender
146+
*/
147+
const task = useFunc(async () => {
148+
await asyncFunc();
149+
});
150+
143151
return (
144152
<div>
145153
<div>asyncFuncRunning:{`${asyncFuncRunning}`}</div>
@@ -163,7 +171,7 @@ export default function () {
163171

164172
<button
165173
onClick={() => {
166-
asyncFunc();
174+
task();
167175
}}
168176
>
169177
test

README.zh-cn.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@ export default function () {
4242
# 详情
4343

4444
```typescript
45-
import { createStore, useStore, Config } from "react-vue-state";
45+
import { createStore, useStore, useFunc, Config } from "react-vue-state";
4646

4747
/**
4848
* 覆盖全局的错误处理
4949
* error 具体错误信息
5050
* funcName 发生错误的函数名称
5151
* kind 在computed,methods,watch,setData那个中发生的错误
5252
*/
53-
Config.onError = (error: any, funcName: string, kind: string) => {
54-
console.log(kind, funcName, error);
53+
Config.onError = (error: any) => {
54+
console.log(error);
5555
// do something
5656
};
5757

@@ -140,6 +140,14 @@ export default function () {
140140
setData,
141141
} = useStore(store);
142142

143+
/**
144+
* 任何函数在运行时都可能会产生错误
145+
* useFunc不仅可以捕获错误还能保证组件在ReRender后地址不会发生改变
146+
*/
147+
const task = useFunc(async () => {
148+
await asyncFunc();
149+
});
150+
143151
return (
144152
<div>
145153
<div>asyncFuncRunning:{`${asyncFuncRunning}`}</div>
@@ -163,7 +171,7 @@ export default function () {
163171

164172
<button
165173
onClick={() => {
166-
asyncFunc();
174+
task();
167175
}}
168176
>
169177
test

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-vue-state",
3-
"version": "1.0.5",
3+
"version": "1.1.0",
44
"description": "react state",
55
"keywords": [
66
"react",

src/computed.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Config } from "./config";
22
import { Context } from "./context";
33
import { Data } from "./data";
44
import { State } from "./state";
5+
import { isAsyncFunction } from "./util";
56

67
class ComputedState<V = any> extends State<V> {
78
private dirty = true;
@@ -23,9 +24,13 @@ class ComputedState<V = any> extends State<V> {
2324

2425
private catchFunc = () => {
2526
try {
26-
return this.func.call(this.funcThis);
27+
const res = this.func.call(this.funcThis);
28+
if (isAsyncFunction(res)) {
29+
throw new Error('"computed" cannot contain async functions');
30+
}
31+
return res;
2732
} catch (error) {
28-
Config.onError(error, this.func.name, "computed");
33+
Config.onError(error);
2934
return this.value;
3035
}
3136
};

src/config.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
11
export class Config {
2-
static onError = (
3-
error: any,
4-
funcName: string,
5-
kind: "computed" | "methods" | "watch" | "context"
6-
) => {
7-
console.error(
8-
"[react vue state error]:\n",
9-
`${kind} => ${funcName} => ${error}`
10-
);
2+
static onError = (error: any) => {
3+
console.error("[react vue state error]:\n", error);
114
};
125
}

src/context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class Context<
5858
try {
5959
return typeof state === "function" ? state(this.funcThis) : state;
6060
} catch (error) {
61-
Config.onError(error, "setData", "context");
61+
Config.onError(error);
6262
return {} as Partial<D["data"]>;
6363
}
6464
})();

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export { createStore } from "./store";
2-
export { useStore } from "./use";
2+
export { useStore, useFunc } from "./use";
33
export { Config } from "./config";

src/methods.ts

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { Config } from "./config";
21
import { Context } from "./context";
32
import { State } from "./state";
43
import { isAsyncFunction } from "./util";
@@ -48,24 +47,17 @@ export class Methods<M extends { [K: string]: (...args: any[]) => any } = any> {
4847
func: (...args: any) => any,
4948
...args: any[]
5049
) => {
51-
try {
52-
const methodsState = this.state[`${key}Running`] as MethodsState;
53-
methodsState.setValue(true);
54-
const res = func.call(this.context.funcThis, ...args);
55-
if (isAsyncFunction(res)) {
56-
return (res as Promise<any>)
57-
.catch((error) => {
58-
Config.onError(error, func.name, "methods");
59-
})
60-
.finally(() => {
61-
methodsState.setValue(false);
62-
});
63-
} else {
50+
const methodsState = this.state[`${key}Running`] as MethodsState;
51+
methodsState.setValue(true);
52+
const res = func.call(this.context.funcThis, ...args);
53+
54+
if (isAsyncFunction(res)) {
55+
return (res as Promise<any>).finally(() => {
6456
methodsState.setValue(false);
65-
return res;
66-
}
67-
} catch (error) {
68-
Config.onError(error, func.name, "methods");
57+
});
58+
} else {
59+
methodsState.setValue(false);
60+
return res;
6961
}
7062
};
7163
}

src/use.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { useMemo, useState, useEffect, useCallback, useRef } from "react";
22
import { Computed } from "./computed";
3+
import { Config } from "./config";
34
import { Context } from "./context";
45
import { Data } from "./data";
56
import { Methods } from "./methods";
67
import { Store } from "./store";
8+
import { isAsyncFunction } from "./util";
79
import { Watch } from "./watch";
810

911
type ObjFuncToObj<T extends Record<string, () => any>> = {
@@ -107,3 +109,26 @@ export const useStore = <
107109

108110
return proxy;
109111
};
112+
113+
export const useFunc = <F extends (...args: any) => any>(func: F) => {
114+
const funcRef = useRef<F>(func);
115+
funcRef.current = useMemo(() => func, [func]);
116+
117+
const funcWrap = useRef<any>();
118+
if (!funcWrap.current) {
119+
funcWrap.current = (...args: any[]) => {
120+
try {
121+
const res = funcRef.current(...args);
122+
if (isAsyncFunction(res)) {
123+
return (res as Promise<any>).catch(Config.onError);
124+
} else {
125+
return res;
126+
}
127+
} catch (error) {
128+
Config.onError(error);
129+
}
130+
};
131+
}
132+
133+
return funcWrap.current as F;
134+
};

src/watch.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ export class Watch<W extends { [k: string]: (...args: any[]) => any } = any> {
3434
const res = func.call(this.context.funcThis, newValue, ...args);
3535
if (isAsyncFunction(res)) {
3636
return (res as Promise<any>).catch((error) => {
37-
Config.onError(error, func.name, "watch");
37+
Config.onError(error);
3838
});
3939
}
4040
} catch (error) {
41-
Config.onError(error, func.name, "watch");
41+
Config.onError(error);
4242
}
4343
};
4444
}

0 commit comments

Comments
 (0)