UNPKG

found-relay

Version:
141 lines (119 loc) 3.96 kB
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; const _excluded = ["match", "Component", "isComponentResolved", "hasComponent", "element", "routeChildren", "querySubscription", "fetched"]; /* eslint-disable @typescript-eslint/ban-types */ import React from 'react'; import { ReactRelayContext } from 'react-relay'; import renderElement from './renderElement'; const { hasOwnProperty } = Object.prototype; class ReadyStateRenderer extends React.Component { constructor(props) { super(props); this.onUpdate = () => { if (!this.props.fetched) { // Ignore subscription updates if our data aren't yet fetched. We'll // rerender anyway once fetching finishes. return; } const { match, Component, isComponentResolved, hasComponent, querySubscription } = this.props; const element = renderElement({ match, Component, isComponentResolved, hasComponent, querySubscription, resolving: false }); this.setState({ element: element || null }); }; const { element: _element, querySubscription: _querySubscription } = props; this.state = { isInitialRender: true, element: _element, propsElement: _element, querySubscription: _querySubscription, selectionReference: _querySubscription.retain(), onUpdate: this.onUpdate }; } componentDidMount() { this.props.querySubscription.subscribe(this.onUpdate); } static getDerivedStateFromProps({ element, querySubscription }, state) { if (state.isInitialRender) { return { isInitialRender: false }; } let nextState = null; if (element !== state.propsElement) { nextState = { element, propsElement: element }; } if (querySubscription !== state.querySubscription) { state.selectionReference.dispose(); state.querySubscription.unsubscribe(state.onUpdate); nextState = nextState || {}; nextState.querySubscription = querySubscription; nextState.selectionReference = querySubscription.retain(); querySubscription.subscribe(state.onUpdate); } return nextState; } componentWillUnmount() { this.state.selectionReference.dispose(); this.props.querySubscription.unsubscribe(this.onUpdate); } render() { const { element } = this.state; if (!element) { return element; } const _this$props = this.props, { routeChildren, querySubscription } = _this$props, ownProps = _objectWithoutPropertiesLoose(_this$props, _excluded); const { props: relayProps } = querySubscription.readyState; if (relayProps) { Object.keys(relayProps).forEach(relayPropName => { // At least on Node v8.x, it's slightly faster to guard the delete here // with this hasOwnProperty check. if (hasOwnProperty.call(ownProps, relayPropName)) { if (process.env.NODE_ENV !== 'production') { console.error(`Ignoring <ReadyStateRenderer> prop \`${relayPropName}\` that shadows a Relay prop from its query \`${querySubscription.getQueryName()}\`. This is most likely due to its parent cloning it and adding extraneous Relay props.`); } // @ts-ignore delete ownProps[relayPropName]; } }); } return /*#__PURE__*/React.createElement(ReactRelayContext.Provider, { value: querySubscription.relayContext }, typeof element === 'function' ? /*#__PURE__*/React.cloneElement(element(routeChildren), ownProps) : /*#__PURE__*/React.cloneElement(element, Object.assign({}, /*#__PURE__*/React.isValidElement(routeChildren) ? { children: routeChildren } : routeChildren, ownProps))); } } export default ReadyStateRenderer;