withRepositories.tsx 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import React from 'react';
  2. import createReactClass from 'create-react-class';
  3. import Reflux from 'reflux';
  4. import {getRepositories} from 'app/actionCreators/repositories';
  5. import RepositoryActions from 'app/actions/repositoryActions';
  6. import {Client} from 'app/api';
  7. import RepositoryStore from 'app/stores/repositoryStore';
  8. import {Organization, Repository} from 'app/types';
  9. import getDisplayName from 'app/utils/getDisplayName';
  10. type DependentProps = {
  11. api: Client;
  12. organization: Organization;
  13. };
  14. type InjectedProps = {
  15. repositories?: Repository[];
  16. repositoriesLoading?: boolean;
  17. repositoriesError?: Error;
  18. };
  19. const INITIAL_STATE: InjectedProps = {
  20. repositories: undefined,
  21. repositoriesLoading: undefined,
  22. repositoriesError: undefined,
  23. };
  24. const withRepositories = <P extends DependentProps>(
  25. WrappedComponent: React.ComponentType<P>
  26. ) =>
  27. createReactClass<
  28. Omit<P, keyof InjectedProps> & Partial<InjectedProps> & DependentProps,
  29. InjectedProps
  30. >({
  31. displayName: `withRepositories(${getDisplayName(WrappedComponent)})`,
  32. mixins: [Reflux.listenTo(RepositoryStore, 'onStoreUpdate') as any],
  33. getInitialState() {
  34. const {organization} = this.props as P & DependentProps;
  35. const orgSlug = organization.slug;
  36. const repoData = RepositoryStore.get();
  37. if (repoData.orgSlug !== orgSlug) {
  38. RepositoryActions.resetRepositories();
  39. }
  40. return repoData.orgSlug === orgSlug
  41. ? {...INITIAL_STATE, ...repoData}
  42. : {...INITIAL_STATE};
  43. },
  44. componentDidMount() {
  45. // XXX(leedongwei): Do not move this function call unless you modify the
  46. // unit test named "prevents repeated calls"
  47. this.fetchRepositories();
  48. },
  49. fetchRepositories() {
  50. const {api, organization} = this.props as P & DependentProps;
  51. const orgSlug = organization.slug;
  52. const repoData = RepositoryStore.get();
  53. // XXX(leedongwei): Do not check the orgSlug here. It would have been
  54. // verified at `getInitialState`. The short-circuit hack in actionCreator
  55. // does not update the orgSlug in the store.
  56. if (
  57. (!repoData.repositories && !repoData.repositoriesLoading) ||
  58. repoData.repositoriesError
  59. ) {
  60. getRepositories(api, {orgSlug});
  61. }
  62. },
  63. onStoreUpdate() {
  64. const repoData = RepositoryStore.get();
  65. this.setState({...repoData});
  66. },
  67. render() {
  68. return <WrappedComponent {...(this.props as P & DependentProps)} {...this.state} />;
  69. },
  70. });
  71. export default withRepositories;