Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inline hoist-non-react-statics to eliminate a dep and help shaking #2066

Merged
merged 2 commits into from
Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@
}
},
"dependencies": {
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/connect.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* eslint-disable valid-jsdoc, @typescript-eslint/no-unused-vars */
import hoistStatics from 'hoist-non-react-statics'
import type { ComponentType } from 'react'
import * as React from 'react'
import { isValidElementType, isContextConsumer } from 'react-is'
Expand Down Expand Up @@ -31,6 +30,7 @@ import type { Subscription } from '../utils/Subscription'
import { createSubscription } from '../utils/Subscription'
import { useIsomorphicLayoutEffect } from '../utils/useIsomorphicLayoutEffect'
import shallowEqual from '../utils/shallowEqual'
import hoistStatics from '../utils/hoistStatics'
import warning from '../utils/warning'

import type {
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {

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

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

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

Expand Down
136 changes: 136 additions & 0 deletions src/utils/hoistStatics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copied directly from:
// https://github.com/mridgway/hoist-non-react-statics/blob/main/src/index.js
// https://unpkg.com/browse/@types/hoist-non-react-statics@3.3.1/index.d.ts

/**
* Copyright 2015, Yahoo! Inc.
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
import type * as React from 'react'
import { ForwardRef, Memo, isMemo } from 'react-is'

const REACT_STATICS = {
childContextTypes: true,
contextType: true,
contextTypes: true,
defaultProps: true,
displayName: true,
getDefaultProps: true,
getDerivedStateFromError: true,
getDerivedStateFromProps: true,
mixins: true,
propTypes: true,
type: true,
} as const

const KNOWN_STATICS = {
name: true,
length: true,
prototype: true,
caller: true,
callee: true,
arguments: true,
arity: true,
} as const

const FORWARD_REF_STATICS = {
$$typeof: true,
render: true,
defaultProps: true,
displayName: true,
propTypes: true,
} as const

const MEMO_STATICS = {
$$typeof: true,
compare: true,
defaultProps: true,
displayName: true,
propTypes: true,
type: true,
} as const

const TYPE_STATICS = {
[ForwardRef]: FORWARD_REF_STATICS,
[Memo]: MEMO_STATICS,
} as const

function getStatics(component: any) {
// React v16.11 and below
if (isMemo(component)) {
return MEMO_STATICS
}

// React v16.12 and above
return TYPE_STATICS[component['$$typeof']] || REACT_STATICS
}

export type NonReactStatics<
S extends React.ComponentType<any>,
C extends {
[key: string]: true
} = {}
> = {
[key in Exclude<
keyof S,
S extends React.MemoExoticComponent<any>
? keyof typeof MEMO_STATICS | keyof C
: S extends React.ForwardRefExoticComponent<any>
? keyof typeof FORWARD_REF_STATICS | keyof C
: keyof typeof REACT_STATICS | keyof typeof KNOWN_STATICS | keyof C
>]: S[key]
}

const defineProperty = Object.defineProperty
const getOwnPropertyNames = Object.getOwnPropertyNames
const getOwnPropertySymbols = Object.getOwnPropertySymbols
const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor
const getPrototypeOf = Object.getPrototypeOf
const objectPrototype = Object.prototype

export default function hoistNonReactStatics<
T extends React.ComponentType<any>,
S extends React.ComponentType<any>,
C extends {
[key: string]: true
} = {}
>(targetComponent: T, sourceComponent: S): T & NonReactStatics<S, C> {
if (typeof sourceComponent !== 'string') {
// don't hoist over string (html) components

if (objectPrototype) {
const inheritedComponent = getPrototypeOf(sourceComponent)
if (inheritedComponent && inheritedComponent !== objectPrototype) {
hoistNonReactStatics(targetComponent, inheritedComponent)
}
}

let keys: (string | symbol)[] = getOwnPropertyNames(sourceComponent)

if (getOwnPropertySymbols) {
keys = keys.concat(getOwnPropertySymbols(sourceComponent))
}

const targetStatics = getStatics(targetComponent)
const sourceStatics = getStatics(sourceComponent)

for (let i = 0; i < keys.length; ++i) {
const key = keys[i]
if (
!KNOWN_STATICS[key as keyof typeof KNOWN_STATICS] &&
!(sourceStatics && sourceStatics[key as keyof typeof sourceStatics]) &&
!(targetStatics && targetStatics[key as keyof typeof targetStatics])
) {
const descriptor = getOwnPropertyDescriptor(sourceComponent, key)
try {
// Avoid failures from read-only properties
defineProperty(targetComponent, key, descriptor!)
} catch (e) {
// ignore
}
}
}
}

return targetComponent as any
}
23 changes: 1 addition & 22 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3263,16 +3263,6 @@ __metadata:
languageName: node
linkType: hard

"@types/hoist-non-react-statics@npm:^3.3.1":
version: 3.3.1
resolution: "@types/hoist-non-react-statics@npm:3.3.1"
dependencies:
"@types/react": "*"
hoist-non-react-statics: ^3.3.0
checksum: 2c0778570d9a01d05afabc781b32163f28409bb98f7245c38d5eaf082416fdb73034003f5825eb5e21313044e8d2d9e1f3fe2831e345d3d1b1d20bcd12270719
languageName: node
linkType: hard

"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1":
version: 2.0.3
resolution: "@types/istanbul-lib-coverage@npm:2.0.3"
Expand Down Expand Up @@ -6588,15 +6578,6 @@ __metadata:
languageName: node
linkType: hard

"hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.2":
version: 3.3.2
resolution: "hoist-non-react-statics@npm:3.3.2"
dependencies:
react-is: ^16.7.0
checksum: b1538270429b13901ee586aa44f4cc3ecd8831c061d06cb8322e50ea17b3f5ce4d0e2e66394761e6c8e152cd8c34fb3b4b690116c6ce2bd45b18c746516cb9e8
languageName: node
linkType: hard

"hosted-git-info@npm:^2.1.4":
version: 2.8.9
resolution: "hosted-git-info@npm:2.8.9"
Expand Down Expand Up @@ -10025,7 +10006,7 @@ __metadata:
languageName: node
linkType: hard

"react-is@npm:^16.13.1, react-is@npm:^16.7.0, react-is@npm:^16.8.1, react-is@npm:^16.8.4":
"react-is@npm:^16.13.1, react-is@npm:^16.8.1, react-is@npm:^16.8.4":
version: 16.13.1
resolution: "react-is@npm:16.13.1"
checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f
Expand Down Expand Up @@ -10126,7 +10107,6 @@ __metadata:
"@testing-library/react-12": "npm:@testing-library/react@^12"
"@testing-library/react-hooks": ^3.4.2
"@testing-library/react-native": ^7.1.0
"@types/hoist-non-react-statics": ^3.3.1
"@types/object-assign": ^4.0.30
"@types/react": ^18
"@types/react-dom": ^18
Expand All @@ -10145,7 +10125,6 @@ __metadata:
eslint-plugin-prettier: ^3.1.4
eslint-plugin-react: ^7.21.5
glob: ^7.1.6
hoist-non-react-statics: ^3.3.2
jest: ^29
jest-environment-jsdom: ^29.5.0
metro-react-native-babel-preset: ^0.76.6
Expand Down
Loading