Skip to content

Commit c560574

Browse files
committed
Attempt to make undux React 18 compatible
1 parent 856cedd commit c560574

File tree

3 files changed

+47
-36
lines changed

3 files changed

+47
-36
lines changed

src/react/connectAs.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,21 @@ export function connectAs<
1818
stores: {
1919
[K in keyof Stores]: ReturnType<Stores[K]['getCurrentSnapshot']>
2020
}
21-
subscriptions: Subscription[]
2221
}
2322

2423
return class extends React.Component<Diff<Props, Stores>, State> {
2524
static displayName = `withStore(${getDisplayName(Component)})`
25+
subscriptions: Subscription[] = []
2626
state = {
2727
stores: mapValues(
2828
stores,
2929
_ =>
3030
_.getCurrentSnapshot() as ReturnType<typeof _['getCurrentSnapshot']>
31-
),
32-
subscriptions: keys(stores).map(k =>
31+
)
32+
}
33+
34+
componentDidMount(): void {
35+
this.subscriptions = keys(stores).map(k =>
3336
stores[k].onAll().subscribe(({ previousValue, value }) => {
3437
if (equals(previousValue, value)) {
3538
return false
@@ -44,7 +47,8 @@ export function connectAs<
4447
}
4548

4649
componentWillUnmount() {
47-
this.state.subscriptions.forEach(_ => _.unsubscribe())
50+
this.subscriptions.forEach(_ => _.unsubscribe())
51+
this.subscriptions = []
4852
}
4953

5054
shouldComponentUpdate(props: Diff<Props, Stores>, state: State) {

src/react/createConnectedStore.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export function createConnectedStore<State extends object>(
3030
ContainerProps<State>,
3131
ContainerState
3232
> {
33-
subscription: Subscription
33+
subscription: Subscription | null = null
3434
storeDefinition: StoreDefinition<State>
3535
constructor(props: ContainerProps<State>) {
3636
super(props)
@@ -45,23 +45,30 @@ export function createConnectedStore<State extends object>(
4545
fx(this.storeDefinition)
4646
}
4747

48+
this.subscription = this._createSubscription()
4849
this.state = {
4950
storeSnapshot: this.storeDefinition.getCurrentSnapshot()
5051
}
52+
}
5153

52-
this.subscription = this.storeDefinition.onAll().subscribe(() =>
54+
_createSubscription = () =>
55+
this.storeDefinition.onAll().subscribe(() =>
5356
this.setState({
5457
storeSnapshot: this.storeDefinition.getCurrentSnapshot()
5558
})
5659
)
60+
61+
componentDidMount(): void {
62+
if (this.subscription == null) {
63+
this.subscription = this._createSubscription()
64+
}
5765
}
5866

5967
componentWillUnmount() {
60-
this.subscription.unsubscribe()
61-
// Let the state get GC'd.
62-
// TODO: Find a more elegant way to do this.
63-
;(this.storeDefinition as any).storeSnapshot = null
64-
;(this as any).storeDefinition = null
68+
if (this.subscription != null) {
69+
this.subscription.unsubscribe()
70+
this.subscription = null
71+
}
6572
}
6673

6774
render() {

src/react/createConnectedStoreAs.tsx

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,16 @@ export function createConnectedStoreAs<
4343
let Context = React.createContext({ __MISSING_PROVIDER__: true } as any)
4444

4545
type ContainerState = {
46-
storeDefinitions: { [K in keyof States]: StoreDefinition<States[K]> | null }
4746
storeSnapshots: { [K in keyof States]: StoreSnapshot<States[K]> | null }
48-
subscriptions: { [K in keyof States]: Subscription }
4947
}
5048

5149
class Container extends React.Component<
5250
ContainerPropsAs<States>,
5351
ContainerState
5452
> {
53+
storeDefinitions: { [K in keyof States]: StoreDefinition<States[K]> }
54+
subscriptions: { [K in keyof States]: Subscription } | null
55+
5556
constructor(props: ContainerPropsAs<States>) {
5657
super(props)
5758

@@ -65,37 +66,36 @@ export function createConnectedStoreAs<
6566
fx(stores as any) // TODO
6667
}
6768

69+
this.storeDefinitions = stores as any
70+
this.subscriptions = this._createSubscriptions()
6871
this.state = {
69-
storeDefinitions: stores as any, // TODO
7072
// TODO
71-
storeSnapshots: mapValues(stores, _ => _.getCurrentSnapshot()) as any,
72-
subscriptions: mapValues(stores, (_, k) =>
73-
_.onAll().subscribe(() =>
74-
this.setState(state => ({
75-
storeSnapshots: Object.assign({}, state.storeSnapshots, {
76-
[k]: _.getCurrentSnapshot()
77-
})
78-
}))
79-
)
73+
storeSnapshots: mapValues(stores, _ => _.getCurrentSnapshot()) as any
74+
}
75+
}
76+
77+
_createSubscriptions = () =>
78+
mapValues(this.storeDefinitions, (_, k) =>
79+
_.onAll().subscribe(() =>
80+
this.setState(state => ({
81+
storeSnapshots: Object.assign({}, state.storeSnapshots, {
82+
[k]: _.getCurrentSnapshot()
83+
})
84+
}))
8085
)
86+
) as any
87+
88+
componentDidMount(): void {
89+
if (this.subscriptions == null) {
90+
this.subscriptions = this._createSubscriptions()
8191
}
8292
}
8393

8494
componentWillUnmount() {
85-
mapValues(this.state.subscriptions, _ => _.unsubscribe())
86-
// Let the state get GC'd.
87-
// TODO: Find a more elegant way to do this.
88-
if (this.state.storeSnapshots) {
95+
if (this.subscriptions != null) {
96+
mapValues(this.subscriptions, _ => _.unsubscribe())
97+
this.subscriptions = null
8998
}
90-
mapValues(this.state.storeSnapshots, _ => ((_ as any).state = null))
91-
mapValues(
92-
this.state.storeSnapshots,
93-
_ => ((_ as any).storeDefinition = null)
94-
)
95-
mapValues(
96-
this.state.storeDefinitions,
97-
_ => ((_ as any).storeSnapshot = null)
98-
)
9999
}
100100

101101
render() {

0 commit comments

Comments
 (0)