Browse Source

ref(js): Swap withConfig HoC to useLegacyStore(ConfigStore) (#29277)

Evan Purkhiser 3 years ago
parent
commit
c8f17470c4

+ 15 - 31
static/app/utils/withConfig.tsx

@@ -1,6 +1,7 @@
 import * as React from 'react';
 
 import ConfigStore from 'app/stores/configStore';
+import {useLegacyStore} from 'app/stores/useLegacyStore';
 import {Config} from 'app/types';
 import getDisplayName from 'app/utils/getDisplayName';
 
@@ -8,42 +9,25 @@ type InjectedConfigProps = {
   config: Config;
 };
 
-type State = {
-  config: Config;
-};
-
 /**
- * Higher order component that passes the config object to the wrapped component
+ * Higher order component that passes the config object to the wrapped
+ * component
  */
 function withConfig<P extends InjectedConfigProps>(
   WrappedComponent: React.ComponentType<P>
 ) {
-  class WithConfig extends React.Component<
-    Omit<P, keyof InjectedConfigProps> & Partial<InjectedConfigProps>,
-    State
-  > {
-    static displayName = `withConfig(${getDisplayName(WrappedComponent)})`;
-
-    state = {config: ConfigStore.getConfig()};
-
-    componentWillUnmount() {
-      this.unsubscribe();
-    }
-
-    unsubscribe = ConfigStore.listen(
-      () => this.setState({config: ConfigStore.getConfig()}),
-      undefined
-    );
-
-    render() {
-      const {config, ...props} = this.props as P;
-      return (
-        <WrappedComponent {...({config: config ?? this.state.config, ...props} as P)} />
-      );
-    }
-  }
-
-  return WithConfig;
+  type Props = Omit<P, keyof InjectedConfigProps> & Partial<InjectedConfigProps>;
+
+  const Wrapper: React.FC<Props> = props => {
+    const config = useLegacyStore(ConfigStore);
+    const allProps = {config, ...props} as P;
+
+    return <WrappedComponent {...allProps} />;
+  };
+
+  Wrapper.displayName = `withConfig(${getDisplayName(WrappedComponent)})`;
+
+  return Wrapper;
 }
 
 export default withConfig;

+ 2 - 1
tests/js/spec/components/sidebar/index.spec.jsx

@@ -1,4 +1,5 @@
 import {mountWithTheme} from 'sentry-test/enzyme';
+import {act} from 'sentry-test/reactTestingLibrary';
 
 import * as incidentActions from 'app/actionCreators/serviceIncidents';
 import SidebarContainer from 'app/components/sidebar';
@@ -144,7 +145,7 @@ describe('Sidebar', function () {
     });
 
     it('can open "Switch Organization" sub-menu', function () {
-      ConfigStore.set('features', new Set(['organizations:create']));
+      act(() => void ConfigStore.set('features', new Set(['organizations:create'])));
       jest.useFakeTimers();
       wrapper = createWrapper();
       wrapper.find('SidebarDropdownActor').simulate('click');

+ 8 - 7
tests/js/spec/utils/withConfig.spec.jsx

@@ -1,4 +1,4 @@
-import {mountWithTheme} from 'sentry-test/enzyme';
+import {act, mountWithTheme, screen} from 'sentry-test/reactTestingLibrary';
 
 import ConfigStore from 'app/stores/configStore';
 import withConfig from 'app/utils/withConfig';
@@ -6,12 +6,13 @@ import withConfig from 'app/utils/withConfig';
 describe('withConfig HoC', function () {
   it('adds config prop', async function () {
     ConfigStore.init();
-    const MyComponent = () => null;
+    const MyComponent = ({config}) => <div>{config.test}</div>;
     const Container = withConfig(MyComponent);
-    const wrapper = mountWithTheme(<Container />);
-    expect(wrapper.find('MyComponent').prop('config')).toEqual({});
-    ConfigStore.set('user', 'foo');
-    wrapper.update();
-    expect(wrapper.find('MyComponent').prop('config')).toEqual({user: 'foo'});
+
+    mountWithTheme(<Container />);
+
+    act(() => void ConfigStore.set('test', 'foo'));
+
+    expect(screen.queryByText('foo')).toBeInTheDocument();
   });
 });