diff --git a/client/src/components/LocationModal.js b/client/src/components/LocationModal.js
index 526c15f..1e83bd4 100644
--- a/client/src/components/LocationModal.js
+++ b/client/src/components/LocationModal.js
@@ -1,6 +1,6 @@
// @flow
-import React from 'react';
+import React, { useCallback } from 'react';
import { AssociatedDropdown } from '@performant-software/semantic-components';
import { withTranslation } from 'react-i18next';
import { Form, Modal } from 'semantic-ui-react';
@@ -30,125 +30,135 @@ const LocationTypes = {
place: 2
};
-const LocationModal = (props: Props) => (
-
-
-
- { props.type === LocationTypes.place && (
-
- Places.save(place).then(({ data }) => data.place)
- }}
- onSearch={(search) => Places.fetchAll({ search, sort_by: 'name' })}
- onSelection={props.onAssociationInputChange.bind(this, 'place_id', 'place')}
- renderOption={Place.toDropdown.bind(this)}
- searchQuery={props.item.place && props.item.place.name}
- value={props.item.place_id || ''}
- />
-
- )}
- { props.type === LocationTypes.artwork && (
-
- Artworks.fetchAll({ search, sort_by: 'artwork_titles.title' })}
- onSelection={props.onAssociationInputChange.bind(this, 'locateable_id', 'locateable')}
- renderOption={Artwork.toDropdown.bind(this)}
- searchQuery={(
- props.item.locateable
- && props.item.locateable.primary_title
- && props.item.locateable.primary_title.title
- )}
- value={props.item.locateable_id || ''}
- />
-
- )}
- { props.type === LocationTypes.person && (
-
- People.save(person).then(({ data }) => data.person)
- }}
- onSearch={(search) => People.fetchAll({ search, sort_by: 'display_name' })}
- onSelection={props.onAssociationInputChange.bind(this, 'locateable_id', 'locateable')}
- renderOption={Person.toDropdown.bind(this)}
- searchQuery={props.item.locateable && props.item.locateable.display_name}
- value={props.item.locateable_id || ''}
- />
-
- )}
-
-
-
-
-
- {
+ /**
+ * Memo-izes the search function.
+ *
+ * @type {function(): function(*): *}
+ */
+ const onSearch = useCallback(() => (search) => Places.fetchAll({ search, sort_by: 'name' }), []);
+
+ return (
+
+
-
- { props.children }
-
-);
+
+ { props.type === LocationTypes.place && (
+
+ Places.save(place).then(({ data }) => data.place)
+ }}
+ onSearch={onSearch}
+ onSelection={props.onAssociationInputChange.bind(this, 'place_id', 'place')}
+ renderOption={Place.toDropdown.bind(this)}
+ searchQuery={props.item.place && props.item.place.name}
+ value={props.item.place_id || ''}
+ />
+
+ )}
+ { props.type === LocationTypes.artwork && (
+
+ Artworks.fetchAll({ search, sort_by: 'artwork_titles.title' })}
+ onSelection={props.onAssociationInputChange.bind(this, 'locateable_id', 'locateable')}
+ renderOption={Artwork.toDropdown.bind(this)}
+ searchQuery={(
+ props.item.locateable
+ && props.item.locateable.primary_title
+ && props.item.locateable.primary_title.title
+ )}
+ value={props.item.locateable_id || ''}
+ />
+
+ )}
+ { props.type === LocationTypes.person && (
+
+ People.save(person).then(({ data }) => data.person)
+ }}
+ onSearch={(search) => People.fetchAll({ search, sort_by: 'display_name' })}
+ onSelection={props.onAssociationInputChange.bind(this, 'locateable_id', 'locateable')}
+ renderOption={Person.toDropdown.bind(this)}
+ searchQuery={props.item.locateable && props.item.locateable.display_name}
+ value={props.item.locateable_id || ''}
+ />
+
+ )}
+
+
+
+
+
+
+
+ { props.children }
+
+ );
+};
export default withTranslation()(LocationModal);
diff --git a/client/src/components/ParticipationModal.js b/client/src/components/ParticipationModal.js
index 3354dcf..0302779 100644
--- a/client/src/components/ParticipationModal.js
+++ b/client/src/components/ParticipationModal.js
@@ -1,6 +1,6 @@
// @flow
-import React from 'react';
+import React, { useCallback } from 'react';
import { AssociatedDropdown } from '@performant-software/semantic-components';
import { withTranslation } from 'react-i18next';
import { Form, Modal } from 'semantic-ui-react';
@@ -26,102 +26,108 @@ const ParticipationTypes = {
person: 1
};
-const ParticipationModal = (props: Props) => (
-
-
-
- { props.type === ParticipationTypes.person && (
-
- People.save(person).then(({ data }) => data.person)
- }}
- onSearch={(search) => People.fetchAll({
- search,
- sort_by: 'display_name',
- per_page: 25
- })}
- onSelection={props.onAssociationInputChange.bind(this, 'person_id', 'person')}
- renderOption={Person.toDropdown.bind(this)}
- searchQuery={props.item.person && props.item.person.display_name}
- value={props.item.person_id || ''}
- />
-
- )}
- { props.type === ParticipationTypes.artwork && (
-
- Artworks.fetchAll({ search, sort_by: 'artwork_titles.title' })}
- onSelection={props.onAssociationInputChange.bind(this, 'participateable_id', 'participateable')}
- renderOption={Artwork.toDropdown.bind(this)}
- searchQuery={(
- props.item.participateable
- && props.item.participateable.primary_title
- && props.item.participateable.primary_title.title
- )}
- value={props.item.participateable_id || ''}
- />
-
- )}
-
-
-
-
- {
+ /**
+ * Memo-izes the search function.
+ *
+ * @type {function(*): Promise>}
+ */
+ const onSearch = useCallback((search) => People.fetchAll({ search, sort_by: 'display_name', per_page: 25 }), []);
+
+ return (
+
+
-
- { props.children }
-
-);
+
+ { props.type === ParticipationTypes.person && (
+
+ People.save(person).then(({ data }) => data.person)
+ }}
+ onSearch={onSearch}
+ onSelection={props.onAssociationInputChange.bind(this, 'person_id', 'person')}
+ renderOption={Person.toDropdown.bind(this)}
+ searchQuery={props.item.person && props.item.person.display_name}
+ value={props.item.person_id || ''}
+ />
+
+ )}
+ { props.type === ParticipationTypes.artwork && (
+
+ Artworks.fetchAll({ search, sort_by: 'artwork_titles.title' })}
+ onSelection={props.onAssociationInputChange.bind(this, 'participateable_id', 'participateable')}
+ renderOption={Artwork.toDropdown.bind(this)}
+ searchQuery={(
+ props.item.participateable
+ && props.item.participateable.primary_title
+ && props.item.participateable.primary_title.title
+ )}
+ value={props.item.participateable_id || ''}
+ />
+
+ )}
+
+
+
+
+
+
+ { props.children }
+
+ );
+};
export default withTranslation()(ParticipationModal);