diff --git a/packages/manager/.changeset/pr-10165-tech-stories-1707412665889.md b/packages/manager/.changeset/pr-10165-tech-stories-1707412665889.md
new file mode 100644
index 00000000000..c791b2cee36
--- /dev/null
+++ b/packages/manager/.changeset/pr-10165-tech-stories-1707412665889.md
@@ -0,0 +1,5 @@
+---
+"@linode/manager": Tech Stories
+---
+
+Update `launchdarkly-react-client-sdk` ([#10165](https://github.com/linode/manager/pull/10165))
diff --git a/packages/manager/package.json b/packages/manager/package.json
index 2900cf692e7..c9f281dafb1 100644
--- a/packages/manager/package.json
+++ b/packages/manager/package.json
@@ -39,7 +39,7 @@
"ipaddr.js": "^1.9.1",
"jspdf": "^2.3.1",
"jspdf-autotable": "^3.5.14",
- "launchdarkly-react-client-sdk": "^3.0.6",
+ "launchdarkly-react-client-sdk": "3.0.10",
"libphonenumber-js": "^1.10.6",
"lodash": "^4.17.21",
"logic-query-parser": "^0.0.5",
diff --git a/packages/manager/src/App.tsx b/packages/manager/src/App.tsx
index 1247e6972c0..04c31a7aff0 100644
--- a/packages/manager/src/App.tsx
+++ b/packages/manager/src/App.tsx
@@ -6,7 +6,6 @@ import {
DocumentTitleSegment,
withDocumentTitleProvider,
} from 'src/components/DocumentTitle';
-import withFeatureFlagConsumer from 'src/containers/withFeatureFlagConsumer.container';
import withFeatureFlagProvider from 'src/containers/withFeatureFlagProvider.container';
import TheApplicationIsOnFire from 'src/features/TheApplicationIsOnFire';
@@ -23,37 +22,35 @@ import { useSetupFeatureFlags } from './useSetupFeatureFlags';
export const App = () => ;
const BaseApp = withDocumentTitleProvider(
- withFeatureFlagProvider(
- withFeatureFlagConsumer(() => {
- const { isLoading } = useInitialRequests();
-
- const { areFeatureFlagsLoading } = useSetupFeatureFlags();
-
- if (isLoading || areFeatureFlagsLoading) {
- return ;
- }
-
- return (
- }>
- {/** Accessibility helper */}
-
- Skip to main content
-
-
- Opens in a new window
- Opens an external site
-
- Opens an external site in a new window
-
-
-
-
-
-
-
- );
- })
- )
+ withFeatureFlagProvider(() => {
+ const { isLoading } = useInitialRequests();
+
+ const { areFeatureFlagsLoading } = useSetupFeatureFlags();
+
+ if (isLoading || areFeatureFlagsLoading) {
+ return ;
+ }
+
+ return (
+ }>
+ {/** Accessibility helper */}
+
+ Skip to main content
+
+
+ Opens in a new window
+ Opens an external site
+
+ Opens an external site in a new window
+
+
+
+
+
+
+
+ );
+ })
);
const GlobalListeners = () => {
diff --git a/packages/manager/src/containers/flags.container.ts b/packages/manager/src/containers/flags.container.ts
new file mode 100644
index 00000000000..f276099513f
--- /dev/null
+++ b/packages/manager/src/containers/flags.container.ts
@@ -0,0 +1,22 @@
+import * as React from 'react';
+
+import { useFlags } from 'src/hooks/useFlags';
+
+import type { FlagSet } from 'src/featureFlags';
+
+export interface WithFeatureFlagProps {
+ flags: FlagSet;
+}
+
+export const withFeatureFlags = (
+ Component: React.ComponentType
+) => {
+ return (props: Props) => {
+ const flags = useFlags();
+
+ return React.createElement(Component, {
+ ...props,
+ flags,
+ });
+ };
+};
diff --git a/packages/manager/src/containers/withFeatureFlagConsumer.container.ts b/packages/manager/src/containers/withFeatureFlagConsumer.container.ts
deleted file mode 100644
index 6ee9b19c54d..00000000000
--- a/packages/manager/src/containers/withFeatureFlagConsumer.container.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { LDClient as _LDClient } from 'launchdarkly-js-client-sdk';
-import { withLDConsumer } from 'launchdarkly-react-client-sdk';
-import { LDProps } from 'launchdarkly-react-client-sdk/lib/withLDConsumer';
-import * as React from 'react';
-import { connect } from 'react-redux';
-import { compose } from 'recompose';
-
-import { FlagSet } from 'src/featureFlags';
-import { MockFeatureFlagState } from 'src/store/mockFeatureFlags';
-import { MapState } from 'src/store/types';
-
-/* eslint-disable-next-line */
-export interface LDClient extends _LDClient {}
-
-export interface FeatureFlagConsumerProps {
- flags: FlagSet;
- ldClient: LDClient;
-}
-
-// We have to provide an HOC around the `withLDConsumer` HOC in order to retrieve mock flags
-// for the custom dev tools.
-export const withFeatureFlagConsumer = (
- Component: React.ComponentType
-) => {
- class WrappedComponent extends React.Component {
- render() {
- return React.createElement(Component, {
- ...this.props,
- flags: {
- // Real LD flags from `withLDConsumer()`.
- ...this.props.flags,
- // Mock flags from Redux.
- ...this.props.mockFlags,
- },
- });
- }
- }
-
- const enhanced = compose(connected, withLDConsumer());
-
- return enhanced(WrappedComponent);
-};
-
-export default withFeatureFlagConsumer;
-
-// Redux connection for the wrapped component.
-interface StateProps {
- mockFlags: MockFeatureFlagState;
-}
-
-const mapStateToProps: MapState = (state) => ({
- mockFlags: state.mockFeatureFlags,
-});
-
-const connected = connect(mapStateToProps);
diff --git a/packages/manager/src/features/Domains/DomainRecords.tsx b/packages/manager/src/features/Domains/DomainRecords.tsx
index ff5ed92a118..1b85fa2debf 100644
--- a/packages/manager/src/features/Domains/DomainRecords.tsx
+++ b/packages/manager/src/features/Domains/DomainRecords.tsx
@@ -21,7 +21,6 @@ import {
propEq,
} from 'ramda';
import * as React from 'react';
-import { compose as recompose } from 'recompose';
import { ActionsPanel } from 'src/components/ActionsPanel/ActionsPanel';
import { Button } from 'src/components/Button/Button';
@@ -37,9 +36,6 @@ import { TableHead } from 'src/components/TableHead';
import { TableRow } from 'src/components/TableRow';
import { TableRowEmpty } from 'src/components/TableRowEmpty/TableRowEmpty';
import { Typography } from 'src/components/Typography';
-import withFeatureFlags, {
- FeatureFlagConsumerProps,
-} from 'src/containers/withFeatureFlagConsumer.container';
import {
getAPIErrorOrDefault,
getErrorStringOrDefault,
@@ -52,7 +48,7 @@ import { DomainRecordActionMenu } from './DomainRecordActionMenu';
import { DomainRecordDrawer } from './DomainRecordDrawer';
import { StyledDiv, StyledGrid, StyledTableCell } from './DomainRecords.styles';
-interface DomainRecordsProps {
+interface Props {
domain: Domain;
domainRecords: DomainRecord[];
updateDomain: (data: { id: number } & UpdateDomainPayload) => Promise;
@@ -79,8 +75,6 @@ interface State {
types: IType[];
}
-type CombinedProps = DomainRecordsProps & FeatureFlagConsumerProps;
-
interface IType {
columns: {
render: (r: Domain | DomainRecord) => JSX.Element | null | string;
@@ -99,8 +93,8 @@ const createLink = (title: string, handler: () => void) => (
);
-class DomainRecords extends React.Component {
- constructor(props: CombinedProps) {
+class DomainRecords extends React.Component {
+ constructor(props: Props) {
super(props);
this.state = {
confirmDialog: {
@@ -112,7 +106,7 @@ class DomainRecords extends React.Component {
};
}
- componentDidUpdate(prevProps: CombinedProps) {
+ componentDidUpdate(prevProps: Props) {
if (
!equals(prevProps.domainRecords, this.props.domainRecords) ||
!equals(prevProps.domain, this.props.domain)
@@ -879,12 +873,10 @@ const prependLinodeNS = compose(
);
const getNSRecords = compose<
- DomainRecordsProps,
+ Props,
DomainRecord[],
DomainRecord[],
DomainRecord[]
>(prependLinodeNS, filter(typeEq('NS')), pathOr([], ['domainRecords']));
-export default recompose(withFeatureFlags)(
- DomainRecords
-);
+export default DomainRecords;
diff --git a/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreate.tsx b/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreate.tsx
index 265c82317e0..95cea371bd4 100644
--- a/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreate.tsx
+++ b/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreate.tsx
@@ -33,10 +33,10 @@ import {
WithAccountProps,
withAccount,
} from 'src/containers/account.container';
+import { WithFeatureFlagProps } from 'src/containers/flags.container';
import { DefaultProps as ImagesProps } from 'src/containers/images.container';
import { RegionsProps } from 'src/containers/regions.container';
import { WithTypesProps } from 'src/containers/types.container';
-import { FeatureFlagConsumerProps } from 'src/containers/withFeatureFlagConsumer.container';
import { WithLinodesProps } from 'src/containers/withLinodes.container';
import { EUAgreementCheckbox } from 'src/features/Account/Agreements/EUAgreementCheckbox';
import { regionSupportsMetadata } from 'src/features/Linodes/LinodesCreate/utilities';
@@ -170,7 +170,7 @@ type InnerProps = WithTypesRegionsAndImages &
type CombinedProps = AllFormStateAndHandlers &
AppsData &
- FeatureFlagConsumerProps &
+ WithFeatureFlagProps &
ImagesProps &
InnerProps &
ReduxStateProps &
diff --git a/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreateContainer.tsx b/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreateContainer.tsx
index 770e8708e11..daa6cc2c3d4 100644
--- a/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreateContainer.tsx
+++ b/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreateContainer.tsx
@@ -26,6 +26,10 @@ import {
WithEventsPollingActionProps,
withEventsPollingActions,
} from 'src/containers/events.container';
+import {
+ WithFeatureFlagProps,
+ withFeatureFlags,
+} from 'src/containers/flags.container';
import withImages, {
DefaultProps as ImagesProps,
} from 'src/containers/images.container';
@@ -35,9 +39,6 @@ import {
} from 'src/containers/profile.container';
import { RegionsProps, withRegions } from 'src/containers/regions.container';
import { WithTypesProps, withTypes } from 'src/containers/types.container';
-import withFlags, {
- FeatureFlagConsumerProps,
-} from 'src/containers/withFeatureFlagConsumer.container';
import {
WithLinodesProps,
withLinodes,
@@ -136,7 +137,7 @@ type CombinedProps = WithSnackbarProps &
WithTypesProps &
WithLinodesProps &
RegionsProps &
- FeatureFlagConsumerProps &
+ WithFeatureFlagProps &
RouteComponentProps<{}, any, any> &
WithProfileProps &
AgreementsProps &
@@ -952,7 +953,7 @@ export default recompose(
withTypes,
connected,
withSnackbar,
- withFlags,
+ withFeatureFlags,
withProfile,
withAgreements,
withQueryClient,
diff --git a/packages/manager/src/features/Linodes/LinodesLanding/LinodesLanding.tsx b/packages/manager/src/features/Linodes/LinodesLanding/LinodesLanding.tsx
index 5d37d449092..b39a91d10b3 100644
--- a/packages/manager/src/features/Linodes/LinodesLanding/LinodesLanding.tsx
+++ b/packages/manager/src/features/Linodes/LinodesLanding/LinodesLanding.tsx
@@ -15,7 +15,6 @@ import {
WithProfileProps,
withProfile,
} from 'src/containers/profile.container';
-import withFeatureFlagConsumer from 'src/containers/withFeatureFlagConsumer.container';
import { BackupsCTA } from 'src/features/Backups/BackupsCTA';
import { MigrateLinode } from 'src/features/Linodes/MigrateLinode/MigrateLinode';
import { DialogType } from 'src/features/Linodes/types';
@@ -432,7 +431,6 @@ const sendGroupByAnalytic = (value: boolean) => {
export const enhanced = compose(
withRouter,
- withFeatureFlagConsumer,
withProfile
);
diff --git a/packages/manager/src/features/Users/UserPermissions.tsx b/packages/manager/src/features/Users/UserPermissions.tsx
index 89141431e01..70b815f7084 100644
--- a/packages/manager/src/features/Users/UserPermissions.tsx
+++ b/packages/manager/src/features/Users/UserPermissions.tsx
@@ -33,9 +33,10 @@ import { TabPanels } from 'src/components/Tabs/TabPanels';
import { Tabs } from 'src/components/Tabs/Tabs';
import { Toggle } from 'src/components/Toggle/Toggle';
import { Typography } from 'src/components/Typography';
-import withFlags, {
- FeatureFlagConsumerProps,
-} from 'src/containers/withFeatureFlagConsumer.container';
+import {
+ WithFeatureFlagProps,
+ withFeatureFlags,
+} from 'src/containers/flags.container';
import {
WithQueryClientProps,
withQueryClient,
@@ -89,7 +90,7 @@ interface State {
type CombinedProps = Props &
WithSnackbarProps &
WithQueryClientProps &
- FeatureFlagConsumerProps;
+ WithFeatureFlagProps;
class UserPermissions extends React.Component {
componentDidMount() {
@@ -815,5 +816,5 @@ class UserPermissions extends React.Component {
export default recompose(
withSnackbar,
withQueryClient,
- withFlags
+ withFeatureFlags
)(UserPermissions);
diff --git a/packages/manager/src/utilities/testHelpers.tsx b/packages/manager/src/utilities/testHelpers.tsx
index 0f872368071..228a8ea9de3 100644
--- a/packages/manager/src/utilities/testHelpers.tsx
+++ b/packages/manager/src/utilities/testHelpers.tsx
@@ -7,7 +7,7 @@ import {
import userEvent from '@testing-library/user-event';
import mediaQuery from 'css-mediaquery';
import { Formik, FormikConfig, FormikValues } from 'formik';
-import { Provider as LDProvider } from 'launchdarkly-react-client-sdk/lib/context';
+import { LDProvider } from 'launchdarkly-react-client-sdk';
import { SnackbarProvider } from 'notistack';
import { mergeDeepRight } from 'ramda';
import * as React from 'react';
@@ -95,10 +95,10 @@ export const wrapWithTheme = (ui: any, options: Options = {}) => {
diff --git a/yarn.lock b/yarn.lock
index a7c93940f90..556a67e9095 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10202,10 +10202,10 @@ language-tags@=1.0.5:
dependencies:
language-subtag-registry "~0.3.2"
-launchdarkly-js-client-sdk@^3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/launchdarkly-js-client-sdk/-/launchdarkly-js-client-sdk-3.1.3.tgz#e046439f0e4f0bfd6d38b9eaa4420a6e40ffc0c7"
- integrity sha512-/JR/ri8z3bEj9RFTTKDjd+con4F1MsWUea1MmBDtFj4gDA0l9NDm1KzhMKiIeoBdmB2rSaeFYe4CaYOEp8IryA==
+launchdarkly-js-client-sdk@^3.1.4:
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/launchdarkly-js-client-sdk/-/launchdarkly-js-client-sdk-3.1.4.tgz#e613cb53412533c07ccf140ae570fc994c59758d"
+ integrity sha512-yq0FeklpVuHMSRz7jfUAfyM7I/659RvGztqJ0Y9G5eN/ZrG1o2W61ZU0Nrv/gqZCtLXjarh/u1otxSFFBjTpHw==
dependencies:
escape-string-regexp "^4.0.0"
launchdarkly-js-sdk-common "5.0.3"
@@ -10219,13 +10219,13 @@ launchdarkly-js-sdk-common@5.0.3:
fast-deep-equal "^2.0.1"
uuid "^8.0.0"
-launchdarkly-react-client-sdk@^3.0.6:
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/launchdarkly-react-client-sdk/-/launchdarkly-react-client-sdk-3.0.6.tgz#5c694a4a013757d2afb5213efd28d9c16af1595e"
- integrity sha512-r7gSshScugjnJB4lJ6mAOMKpV4Pj/wUks3tsRHdfeXgER9jPdxmZOAkm0besMjK0S7lfQdjxJ2KIXrh+Mn1sQA==
+launchdarkly-react-client-sdk@3.0.10:
+ version "3.0.10"
+ resolved "https://registry.yarnpkg.com/launchdarkly-react-client-sdk/-/launchdarkly-react-client-sdk-3.0.10.tgz#33816d939d9bd18b0723c0fd30b4772f2429f3de"
+ integrity sha512-ssb3KWe9z42+q8X2u32OrlDntGLsv0NP/p4E2Hx4O9RU0OeFm9v6omOlIk9SMsYEQD4QzLSXAp5L3cSN2ssLlA==
dependencies:
hoist-non-react-statics "^3.3.2"
- launchdarkly-js-client-sdk "^3.1.3"
+ launchdarkly-js-client-sdk "^3.1.4"
lodash.camelcase "^4.3.0"
lazy-ass@^1.6.0: