import { Component, ReactNode } from 'react'; import { connect } from 'react-redux'; import get from 'lodash/get'; import { crudGetManyAccumulate as crudGetManyAccumulateAction } from '../../actions'; import { getReferencesByIds } from '../../reducer/admin/references/oneToMany'; import { ReduxState, Record, RecordMap, Dispatch, Sort, Identifier, } from '../../types'; interface ChildrenFuncParams { loadedOnce: boolean; ids: Identifier[]; data: RecordMap; referenceBasePath: string; currentSort: Sort; } interface Props { basePath: string; children: (params: ChildrenFuncParams) => ReactNode; crudGetManyAccumulate: Dispatch; data?: RecordMap; ids: Identifier[]; record?: Record; reference: string; resource: string; source: string; } /** * A container component that fetches records from another resource specified * by an array of *ids* in current record. * * You must define the fields to be passed to the iterator component as children. * * @example Display all the products of the current order as datagrid * // order = { * // id: 123, * // product_ids: [456, 457, 458], * // } * * * * * * * * * * @example Display all the categories of the current product as a list of chips * // product = { * // id: 456, * // category_ids: [11, 22, 33], * // } * * * * * * */ export class UnconnectedReferenceArrayFieldController extends Component { componentDidMount() { this.fetchReferences(); } componentWillReceiveProps(nextProps) { if ( (this.props.record || { id: undefined }).id !== (nextProps.record || {}).id ) { this.fetchReferences(nextProps); } } fetchReferences({ crudGetManyAccumulate, reference, ids } = this.props) { crudGetManyAccumulate(reference, ids); } render() { const { resource, reference, data, ids, children, basePath, } = this.props; const referenceBasePath = basePath.replace(resource, reference); // FIXME obviously very weak return children({ loadedOnce: data != undefined, // eslint-disable-line eqeqeq ids, data, referenceBasePath, currentSort: { field: 'id', order: 'ASC', }, }); } } const mapStateToProps = (state: ReduxState, props: Props) => { const { record, source, reference } = props; const ids = get(record, source) || []; return { data: getReferencesByIds(state, reference, ids), ids, }; }; const ReferenceArrayFieldController = connect( mapStateToProps, { crudGetManyAccumulate: crudGetManyAccumulateAction, } )(UnconnectedReferenceArrayFieldController); export default ReferenceArrayFieldController;