withProjectsSpecified.tsx 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import * as React from 'react';
  2. import createReactClass from 'create-react-class';
  3. import xor from 'lodash/xor';
  4. import Reflux from 'reflux';
  5. import ProjectsStore from 'app/stores/projectsStore';
  6. import {Project} from 'app/types';
  7. import getDisplayName from 'app/utils/getDisplayName';
  8. type Props = {
  9. projects?: Project[];
  10. specificProjectSlugs?: string[];
  11. };
  12. type InjectedProjectsProps = {
  13. loadingProjects: boolean;
  14. } & Props;
  15. type State = {
  16. projects: Project[];
  17. loading: boolean;
  18. };
  19. /**
  20. * Higher order component that takes specificProjectSlugs and provides list of that projects from ProjectsStore
  21. */
  22. const withProjectsSpecified = <P extends InjectedProjectsProps>(
  23. WrappedComponent: React.ComponentType<P>
  24. ) =>
  25. createReactClass<Props & Omit<P, keyof InjectedProjectsProps>, State>({
  26. displayName: `withProjectsSpecified(${getDisplayName(WrappedComponent)})`,
  27. mixins: [Reflux.listenTo(ProjectsStore, 'onProjectUpdate') as any],
  28. getInitialState() {
  29. return ProjectsStore.getState(this.props.specificProjectSlugs);
  30. },
  31. UNSAFE_componentWillReceiveProps(nextProps: Props) {
  32. const {specificProjectSlugs} = this.props;
  33. if (xor(nextProps.specificProjectSlugs, specificProjectSlugs).length) {
  34. this.setState(ProjectsStore.getState(nextProps.specificProjectSlugs));
  35. }
  36. },
  37. onProjectUpdate() {
  38. this.setState(ProjectsStore.getState(this.props.specificProjectSlugs));
  39. },
  40. render() {
  41. return (
  42. <WrappedComponent
  43. {...(this.props as P)}
  44. projects={this.state.projects as Project[]}
  45. loadingProjects={this.state.loading}
  46. />
  47. );
  48. },
  49. });
  50. export default withProjectsSpecified;