Skip to content

Commit c71507d

Browse files
Added symbol props support for state created by useAsyncDeepState hook;
Added toJSON method for the state object;
1 parent 718a0e8 commit c71507d

File tree

3 files changed

+40
-11
lines changed

3 files changed

+40
-11
lines changed

lib/use-async-effect.js

+34-8
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,31 @@ const useFactory = (factory, args) => {
469469
return current;
470470
}
471471

472+
const assignState= (obj, target)=>{
473+
Object.assign(obj, target);
474+
const symbols = Object.getOwnPropertySymbols(target);
475+
let i = symbols.length;
476+
while (i-- > 0) {
477+
const symbol = symbols[i];
478+
obj[symbol] = target[symbol];
479+
}
480+
return obj;
481+
}
482+
483+
class ProtoState {
484+
constructor(initialState) {
485+
initialState && assignState(this, initialState);
486+
}
487+
488+
toJSON() {
489+
const obj = {};
490+
let target = this;
491+
do {
492+
assignState(obj, target);
493+
} while ((target = Object.getPrototypeOf(target)) && target !== Object.prototype);
494+
return obj;
495+
}
496+
}
472497

473498
/**
474499
* useAsyncDeepState hook whose setter returns a promise
@@ -484,26 +509,27 @@ const useAsyncDeepState = (initialValue, {watch= true}= {}) => {
484509
throw TypeError('initial state must be a plain object');
485510
}
486511

487-
const state= initialValue? Object.assign({}, initialValue) : {};
512+
const state = new ProtoState(initialValue);
488513

489514
Object.assign(current, {
490515
state,
491-
oldState: null,
516+
oldState: new ProtoState(initialValue),
492517
callbacks: new Map()
493518
})
494519
}
495520

496-
const [state, setState] = useState(!current.inited && Object.create(current.state));
497-
498-
current.inited= true;
521+
const [state, setState] = useState(!current.inited && Object.freeze(Object.create(current.state)));
499522

500523
watch && useEffect(()=>{
524+
if (!current.inited) return;
501525
const data= [state, current.oldState];
502526
current.callbacks.forEach(cb=> cb(data));
503527
current.callbacks.clear();
504-
current.oldState= Object.assign({}, current.state);
528+
current.oldState= new ProtoState(current.state);
505529
}, [state]);
506530

531+
current.inited= true;
532+
507533
return [
508534
state,
509535
/**
@@ -522,7 +548,7 @@ const useAsyncDeepState = (initialValue, {watch= true}= {}) => {
522548
}
523549

524550
setState((state)=>{
525-
if(newState == null || isEqualObjects(Object.assign(current.state, newState), current.oldState)){
551+
if(newState == null || isEqualObjects(assignState(current.state, newState), current.oldState)){
526552
scope && cb([state, current.oldState]);
527553
return state;
528554
}
@@ -532,7 +558,7 @@ const useAsyncDeepState = (initialValue, {watch= true}= {}) => {
532558
scope.onDone(() => current.callbacks.delete(scope))
533559
}
534560

535-
return Object.create(current.state)
561+
return Object.freeze(Object.create(current.state));
536562
});
537563
}
538564

playground/src/TestComponent7.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import {
44
} from "../../lib/use-async-effect";
55

66
export default function TestComponent7(props) {
7+
const symbol= Symbol('test');
78

89
const [state, setState] = useAsyncDeepState({
910
foo: 123,
1011
bar: 456,
11-
counter: 0
12+
counter: 0,
13+
[symbol]: "test"
1214
});
1315

1416
return (
@@ -20,7 +22,8 @@ export default function TestComponent7(props) {
2022
return {counter: state.counter + 1}
2123
});
2224

23-
console.log(`Updated: ${newState.counter}, old: ${oldState.counter}`);
25+
console.log(`Updated counter: ${newState.counter}, old counter: ${oldState.counter}`);
26+
console.log('Updated state: ', newState.toJSON(),' old state: ', oldState.toJSON());
2427
}}>Inc</button>
2528
<button onClick={()=>setState((state)=>{
2629
counter: state.counter

playground/src/TestComponent9.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default function TestComponent7(props) {
1616
yield CPromise.delay(delay);
1717
}
1818
},
19-
{ states: true, cancelPrevios: true }
19+
{ states: true, cancelPrevious: true }
2020
);
2121

2222
return (

0 commit comments

Comments
 (0)