import * as React from 'react' ; import { cloneElement , Children , useEffect , useState , memo , FC , ReactElement , } from 'react' ; import get from 'lodash/get' ; import { Identifier , ListContextProvider , useRecordContext } from 'ra-core' ; import { PublicFieldProps , InjectedFieldProps , fieldPropTypes } from './types' ; import PropTypes from 'prop-types' ; const initialState = { data : { } , ids : [ ] , } ; const getDataAndIds = ( record , source , fieldKey ) : State => { const list = get ( record , source ) ; if ( ! list ) { return initialState ; } return fieldKey ? { data : list . reduce ( ( prev , item ) => { prev [ item [ fieldKey ] ] = item ; return prev ; } , { } ) , ids : list . map ( item => item [ fieldKey ] ) , } : { data : list . reduce ( ( prev , item ) => { prev [ JSON . stringify ( item ) ] = item ; return prev ; } , { } ) , ids : list . map ( JSON . stringify ) , } ; } ; example example example example export const ArrayField = memo ( props => { const { addLabel , basePath , children , record : _record , resource , sortable , source , fieldKey , ... rest } = props ; const record = useRecordContext ( props ) ; const [ ids , setIds ] = useState ( initialState . ids ) ; const [ data , setData ] = useState ( initialState . data ) ; useEffect ( ( ) => { const { ids , data } = getDataAndIds ( record , source , fieldKey ) ; setIds ( ids ) ; setData ( data ) ; } , [ record , source , fieldKey ] ) ; return ( < ListContextProvider value = { { ids , data , loading : false , basePath , selectedIds : [ ] , currentSort : { field : null , order : null } , displayedFilters : null , filterValues : null , hasCreate : null , hideFilter : null , loaded : true , onSelect : null , onToggleItem : null , onUnselectItems : null , page : null , perPage : null , resource , setFilters : null , setPage : null , setPerPage : null , setSort : null , showFilter : null , total : ids . length , } } > { cloneElement ( Children . only ( children ) , { ids , data , loading : false , basePath , currentSort : { field : null , order : null } , resource , ... rest , } ) } < /ListContextProvider>); } ) ; ArrayField . defaultProps = { addLabel : true , } ; ArrayField . propTypes = { ... fieldPropTypes , fieldKey : PropTypes . string , } ; export interface ArrayFieldProps extends PublicFieldProps , InjectedFieldProps { fieldKey ? : string ; children : ReactElement ; } interface State { data : object ; ids : Identifier [ ] ; } ArrayField . displayName = 'ArrayField' ; export default ArrayField ;