React-admin: Migrate useReferenceInputController to use useDataProvider instead of sagas

Created on 14 Mar 2020  路  5Comments  路  Source: marmelab/react-admin

The requests made by the <ReferenceInput> component aren't cached because their controller still uses the CrudGetMatchingAccumulate action creator. That means that the dataProvider.getList() it makes to fetch the possible references is done by the old fetch saga (called by the accumulate saga) instead of the useDataProvider hook. As the cache is only implemented in the new hook, <ReferenceInput> doesn't use the cache.

We need to migrate the useReferenceInputController code so that it doesn't use the accumulate saga anymore.

Seen in #4386

Most helpful comment

@AymanElarian If you're in need of a temporary solution, here's a recipe I came up with that could potentially work for you. Main idea being defaulting to a disabled text input and have user click on it to transform into a reference input (which will then make the api calls, if needed). At least for me, it's often the case that 20 lines will load in and maybe 1,2 or none will need edit. If your users need to edit most/all, then this obviously isn't a good solution at all for you.

const ConditionalInput = ({ record, source, currentLines, ...props }) => {
    const [enableEdit, setEnableEdit] = useState(false);
    const getSource = useCallback((scopedSource: string) => `${source}.${scopedSource}`, [source]);
    const currentIndex = useMemo(() => parseInt(props.id.match(/\d+/g)), [props.id]);
    const lineValues = currentLines[currentIndex];

    if (!lineValues) {
        return null;
    }

    if (enableEdit || !lineValues.asset_id) {
        return (
            <ReferenceInput
                label="Asset"
                source={getSource('asset_id')}
                reference="parent-assets"
                filterToQuery={(searchText: string) => ({
                    logic: 'or',
                    complexFilter: assetFilter(searchText),
                })}
                sort={{ field: 'parent_number', order: 'ASC' }}
                allowEmpty
                validate={[required()]}
                onChange={ev => setEnableEdit(true)}
                {...props}
            >
                <AutocompleteInput
                    shouldRenderSuggestions={(val: string) => 'undefined' !== typeof val && 2 < val.trim().length}
                    optionText={assetsOptionRenderer}
                />
            </ReferenceInput>
        );
    }

    return (
        <TextInput
            disabled
            source={getSource('asset_description')}
            label="Asset Description"
            onClick={ev => setEnableEdit(true)}
            helperText="Click to Edit"
            value={lineValues.asset_name ? lineLabel(lineValues) : ''}
            {...props}
        />
    );
};

All 5 comments

We're looking forward to this, it will definitely help us in our project. Thank y'all very much!

any update about this ,, it will definitely help us in our project. all our SimpleFormIterator is slow as its make http request for fetch for each child and app/browser hang

@AymanElarian If you're in need of a temporary solution, here's a recipe I came up with that could potentially work for you. Main idea being defaulting to a disabled text input and have user click on it to transform into a reference input (which will then make the api calls, if needed). At least for me, it's often the case that 20 lines will load in and maybe 1,2 or none will need edit. If your users need to edit most/all, then this obviously isn't a good solution at all for you.

const ConditionalInput = ({ record, source, currentLines, ...props }) => {
    const [enableEdit, setEnableEdit] = useState(false);
    const getSource = useCallback((scopedSource: string) => `${source}.${scopedSource}`, [source]);
    const currentIndex = useMemo(() => parseInt(props.id.match(/\d+/g)), [props.id]);
    const lineValues = currentLines[currentIndex];

    if (!lineValues) {
        return null;
    }

    if (enableEdit || !lineValues.asset_id) {
        return (
            <ReferenceInput
                label="Asset"
                source={getSource('asset_id')}
                reference="parent-assets"
                filterToQuery={(searchText: string) => ({
                    logic: 'or',
                    complexFilter: assetFilter(searchText),
                })}
                sort={{ field: 'parent_number', order: 'ASC' }}
                allowEmpty
                validate={[required()]}
                onChange={ev => setEnableEdit(true)}
                {...props}
            >
                <AutocompleteInput
                    shouldRenderSuggestions={(val: string) => 'undefined' !== typeof val && 2 < val.trim().length}
                    optionText={assetsOptionRenderer}
                />
            </ReferenceInput>
        );
    }

    return (
        <TextInput
            disabled
            source={getSource('asset_description')}
            label="Asset Description"
            onClick={ev => setEnableEdit(true)}
            helperText="Click to Edit"
            value={lineValues.asset_name ? lineLabel(lineValues) : ''}
            {...props}
        />
    );
};

@fancyaction good job Man ! it fit and solve my case very good , thank you

Fixed by #5016

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Kmaschta picture Kmaschta  路  3Comments

fzaninotto picture fzaninotto  路  3Comments

aserrallerios picture aserrallerios  路  3Comments

kikill95 picture kikill95  路  3Comments

alukito picture alukito  路  3Comments