diff --git a/packages/@sanity/base/sanity.json b/packages/@sanity/base/sanity.json index a7b9e5683eac..956350e9541d 100644 --- a/packages/@sanity/base/sanity.json +++ b/packages/@sanity/base/sanity.json @@ -187,6 +187,10 @@ "name": "part:@sanity/base/query-container", "description": "Wraps a query and passes down results as props to its child component" }, + { + "name": "part:@sanity/base/with-referring-documents", + "description": "A utility component that takes a document id and calls its child render prop with a list of documents referring to it" + }, { "name": "part:@sanity/base/theme/layout/resets-style", "description": "Provides resets for resetting browser styling" @@ -410,6 +414,10 @@ "implements": "part:@sanity/base/query-container", "path": "components/QueryContainer" }, + { + "implements": "part:@sanity/base/with-referring-documents", + "path": "components/WithReferringDocuments" + }, { "implements": "part:@sanity/base/locale/formatters", "path": "components/IntlWrapper.js" diff --git a/packages/@sanity/base/src/components/WithReferringDocuments.js b/packages/@sanity/base/src/components/WithReferringDocuments.js new file mode 100644 index 000000000000..cf3e0e033d5f --- /dev/null +++ b/packages/@sanity/base/src/components/WithReferringDocuments.js @@ -0,0 +1,25 @@ +import documentStore from 'part:@sanity/base/datastore/document' +import {withPropsStream} from 'react-props-stream' +import {concat, of} from 'rxjs' +import {distinctUntilChanged, map, switchMap} from 'rxjs/operators' + +const loadProps = receivedProps$ => + receivedProps$.pipe( + distinctUntilChanged((prev, next) => prev.id === next.id), + switchMap(receivedProps => + concat( + of({...receivedProps, referringDocuments: [], isLoading: true}), + documentStore.query('*[references($docId)] [0...101]', {docId: receivedProps.id}).pipe( + map(event => ({ + ...receivedProps, + referringDocuments: event.documents, + isLoading: false + })) + ) + ) + ) + ) + +export const WithReferringDocuments = withPropsStream(loadProps, ({children, ...props}) => + children(props) +) diff --git a/packages/@sanity/desk-tool/src/components/enhanceWithReferringDocuments.js b/packages/@sanity/desk-tool/src/components/enhanceWithReferringDocuments.js index 8a33a4396b81..f3367e8d36eb 100644 --- a/packages/@sanity/desk-tool/src/components/enhanceWithReferringDocuments.js +++ b/packages/@sanity/desk-tool/src/components/enhanceWithReferringDocuments.js @@ -1,51 +1,26 @@ import React from 'react' import PropTypes from 'prop-types' -import documentStore from 'part:@sanity/base/datastore/document' +import {WithReferringDocuments} from 'part:@sanity/base/with-referring-documents' -export default function withReferringDocuments(Component) { - return class extends React.PureComponent { - static displayName = `enhanceWithAvailHeight(${Component.displayName || Component.name})` - - static propTypes = { - published: PropTypes.object - } - - state = { - isLoading: false, - referringDocuments: [] - } - - componentDidMount() { - const {published} = this.props - if (!published) { - return - } - this.setState({isLoading: true}) - this.refSubscription = documentStore - .query('*[references($docId)] [0...101]', {docId: published._id}) - .subscribe(event => { - this.setState({ - referringDocuments: event.documents || [], - isLoading: false - }) - }) - } - - componentWillUnmount() { - if (this.refSubscription) { - this.refSubscription.unsubscribe() - } - } +export default function enhanceWithReferringDocuments(Component) { + function EnhancedWithReferringDocuments(props) { + return ( + + {({isLoading, referringDocuments}) => ( + + )} + + ) + } - render() { - const {isLoading, referringDocuments} = this.state - return ( - - ) - } + EnhancedWithReferringDocuments.displayName = `enhanceWithReferringDocuments(${Component.displayName || + Component.name})` + EnhancedWithReferringDocuments.propTypes = { + published: PropTypes.object } + return EnhancedWithReferringDocuments }