Skip to content

Commit 5a406a9

Browse files
authored
Merge pull request #2066 from reduxjs/feature/port-hoist-statics
2 parents bec3fa7 + c75af3a commit 5a406a9

File tree

5 files changed

+139
-26
lines changed

5 files changed

+139
-26
lines changed

Diff for: package.json

-2
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@
7070
}
7171
},
7272
"dependencies": {
73-
"@types/hoist-non-react-statics": "^3.3.1",
7473
"@types/use-sync-external-store": "^0.0.3",
75-
"hoist-non-react-statics": "^3.3.2",
7674
"react-is": "^18.0.0",
7775
"use-sync-external-store": "^1.0.0"
7876
},

Diff for: src/components/connect.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
/* eslint-disable valid-jsdoc, @typescript-eslint/no-unused-vars */
2-
import hoistStatics from 'hoist-non-react-statics'
32
import type { ComponentType } from 'react'
43
import * as React from 'react'
54
import { isValidElementType, isContextConsumer } from 'react-is'
@@ -31,6 +30,7 @@ import type { Subscription } from '../utils/Subscription'
3130
import { createSubscription } from '../utils/Subscription'
3231
import { useIsomorphicLayoutEffect } from '../utils/useIsomorphicLayoutEffect'
3332
import shallowEqual from '../utils/shallowEqual'
33+
import hoistStatics from '../utils/hoistStatics'
3434
import warning from '../utils/warning'
3535

3636
import type {

Diff for: src/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type {
77

88
import type { Action, UnknownAction, Dispatch } from 'redux'
99

10-
import type { NonReactStatics } from 'hoist-non-react-statics'
10+
import type { NonReactStatics } from './utils/hoistStatics'
1111

1212
import type { ConnectProps } from './components/connect'
1313

Diff for: src/utils/hoistStatics.ts

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copied directly from:
2+
// https://github.com/mridgway/hoist-non-react-statics/blob/main/src/index.js
3+
// https://unpkg.com/browse/@types/[email protected]/index.d.ts
4+
5+
/**
6+
* Copyright 2015, Yahoo! Inc.
7+
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
8+
*/
9+
import type * as React from 'react'
10+
import { ForwardRef, Memo, isMemo } from 'react-is'
11+
12+
const REACT_STATICS = {
13+
childContextTypes: true,
14+
contextType: true,
15+
contextTypes: true,
16+
defaultProps: true,
17+
displayName: true,
18+
getDefaultProps: true,
19+
getDerivedStateFromError: true,
20+
getDerivedStateFromProps: true,
21+
mixins: true,
22+
propTypes: true,
23+
type: true,
24+
} as const
25+
26+
const KNOWN_STATICS = {
27+
name: true,
28+
length: true,
29+
prototype: true,
30+
caller: true,
31+
callee: true,
32+
arguments: true,
33+
arity: true,
34+
} as const
35+
36+
const FORWARD_REF_STATICS = {
37+
$$typeof: true,
38+
render: true,
39+
defaultProps: true,
40+
displayName: true,
41+
propTypes: true,
42+
} as const
43+
44+
const MEMO_STATICS = {
45+
$$typeof: true,
46+
compare: true,
47+
defaultProps: true,
48+
displayName: true,
49+
propTypes: true,
50+
type: true,
51+
} as const
52+
53+
const TYPE_STATICS = {
54+
[ForwardRef]: FORWARD_REF_STATICS,
55+
[Memo]: MEMO_STATICS,
56+
} as const
57+
58+
function getStatics(component: any) {
59+
// React v16.11 and below
60+
if (isMemo(component)) {
61+
return MEMO_STATICS
62+
}
63+
64+
// React v16.12 and above
65+
return TYPE_STATICS[component['$$typeof']] || REACT_STATICS
66+
}
67+
68+
export type NonReactStatics<
69+
S extends React.ComponentType<any>,
70+
C extends {
71+
[key: string]: true
72+
} = {}
73+
> = {
74+
[key in Exclude<
75+
keyof S,
76+
S extends React.MemoExoticComponent<any>
77+
? keyof typeof MEMO_STATICS | keyof C
78+
: S extends React.ForwardRefExoticComponent<any>
79+
? keyof typeof FORWARD_REF_STATICS | keyof C
80+
: keyof typeof REACT_STATICS | keyof typeof KNOWN_STATICS | keyof C
81+
>]: S[key]
82+
}
83+
84+
const defineProperty = Object.defineProperty
85+
const getOwnPropertyNames = Object.getOwnPropertyNames
86+
const getOwnPropertySymbols = Object.getOwnPropertySymbols
87+
const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor
88+
const getPrototypeOf = Object.getPrototypeOf
89+
const objectPrototype = Object.prototype
90+
91+
export default function hoistNonReactStatics<
92+
T extends React.ComponentType<any>,
93+
S extends React.ComponentType<any>,
94+
C extends {
95+
[key: string]: true
96+
} = {}
97+
>(targetComponent: T, sourceComponent: S): T & NonReactStatics<S, C> {
98+
if (typeof sourceComponent !== 'string') {
99+
// don't hoist over string (html) components
100+
101+
if (objectPrototype) {
102+
const inheritedComponent = getPrototypeOf(sourceComponent)
103+
if (inheritedComponent && inheritedComponent !== objectPrototype) {
104+
hoistNonReactStatics(targetComponent, inheritedComponent)
105+
}
106+
}
107+
108+
let keys: (string | symbol)[] = getOwnPropertyNames(sourceComponent)
109+
110+
if (getOwnPropertySymbols) {
111+
keys = keys.concat(getOwnPropertySymbols(sourceComponent))
112+
}
113+
114+
const targetStatics = getStatics(targetComponent)
115+
const sourceStatics = getStatics(sourceComponent)
116+
117+
for (let i = 0; i < keys.length; ++i) {
118+
const key = keys[i]
119+
if (
120+
!KNOWN_STATICS[key as keyof typeof KNOWN_STATICS] &&
121+
!(sourceStatics && sourceStatics[key as keyof typeof sourceStatics]) &&
122+
!(targetStatics && targetStatics[key as keyof typeof targetStatics])
123+
) {
124+
const descriptor = getOwnPropertyDescriptor(sourceComponent, key)
125+
try {
126+
// Avoid failures from read-only properties
127+
defineProperty(targetComponent, key, descriptor!)
128+
} catch (e) {
129+
// ignore
130+
}
131+
}
132+
}
133+
}
134+
135+
return targetComponent as any
136+
}

Diff for: yarn.lock

+1-22
Original file line numberDiff line numberDiff line change
@@ -3263,16 +3263,6 @@ __metadata:
32633263
languageName: node
32643264
linkType: hard
32653265

3266-
"@types/hoist-non-react-statics@npm:^3.3.1":
3267-
version: 3.3.1
3268-
resolution: "@types/hoist-non-react-statics@npm:3.3.1"
3269-
dependencies:
3270-
"@types/react": "*"
3271-
hoist-non-react-statics: ^3.3.0
3272-
checksum: 2c0778570d9a01d05afabc781b32163f28409bb98f7245c38d5eaf082416fdb73034003f5825eb5e21313044e8d2d9e1f3fe2831e345d3d1b1d20bcd12270719
3273-
languageName: node
3274-
linkType: hard
3275-
32763266
"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1":
32773267
version: 2.0.3
32783268
resolution: "@types/istanbul-lib-coverage@npm:2.0.3"
@@ -6588,15 +6578,6 @@ __metadata:
65886578
languageName: node
65896579
linkType: hard
65906580

6591-
"hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.2":
6592-
version: 3.3.2
6593-
resolution: "hoist-non-react-statics@npm:3.3.2"
6594-
dependencies:
6595-
react-is: ^16.7.0
6596-
checksum: b1538270429b13901ee586aa44f4cc3ecd8831c061d06cb8322e50ea17b3f5ce4d0e2e66394761e6c8e152cd8c34fb3b4b690116c6ce2bd45b18c746516cb9e8
6597-
languageName: node
6598-
linkType: hard
6599-
66006581
"hosted-git-info@npm:^2.1.4":
66016582
version: 2.8.9
66026583
resolution: "hosted-git-info@npm:2.8.9"
@@ -10025,7 +10006,7 @@ __metadata:
1002510006
languageName: node
1002610007
linkType: hard
1002710008

10028-
"react-is@npm:^16.13.1, react-is@npm:^16.7.0, react-is@npm:^16.8.1, react-is@npm:^16.8.4":
10009+
"react-is@npm:^16.13.1, react-is@npm:^16.8.1, react-is@npm:^16.8.4":
1002910010
version: 16.13.1
1003010011
resolution: "react-is@npm:16.13.1"
1003110012
checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f
@@ -10126,7 +10107,6 @@ __metadata:
1012610107
"@testing-library/react-12": "npm:@testing-library/react@^12"
1012710108
"@testing-library/react-hooks": ^3.4.2
1012810109
"@testing-library/react-native": ^7.1.0
10129-
"@types/hoist-non-react-statics": ^3.3.1
1013010110
"@types/object-assign": ^4.0.30
1013110111
"@types/react": ^18
1013210112
"@types/react-dom": ^18
@@ -10145,7 +10125,6 @@ __metadata:
1014510125
eslint-plugin-prettier: ^3.1.4
1014610126
eslint-plugin-react: ^7.21.5
1014710127
glob: ^7.1.6
10148-
hoist-non-react-statics: ^3.3.2
1014910128
jest: ^29
1015010129
jest-environment-jsdom: ^29.5.0
1015110130
metro-react-native-babel-preset: ^0.76.6

0 commit comments

Comments
 (0)