0

Invalid hook call. Hooks can only be called inside of the body of a function component.

I am trying to create a hook to load options in react-select. Here's my code -

import React, { useEffect } from "react";
import { useDispatch } from 'react-redux';

import {isEmpty, generateMenuEndPoint} from '../../helper/commonFunc';
import AsyncSelect from 'react-select/async';

import {searchMenuAction} from '../../app/actions/appAction';

export function AsyncSelectHooks(props) {
    const { index, formElement, isClearable, multiSelect, isDisabled, defaultOptions, parent, searchMenuDetails } = props;
    let { handleSelectInputChange, handleSelectChange, getOptionValue } = props.parent;

    const useFetchMenu = (searchItem) => {
        const dispatch = useDispatch();

        useEffect(() => {
                if(!isEmpty(searchMenuDetails)) {
                    let menuDetails = generateMenuEndPoint(searchMenuDetails, searchItem);

                    return new Promise((resolve, reject) => {
                        dispatch(searchMenuAction(menuDetails, (response) => {
                            resolve(response[menuDetails.getData]);
                        }));
                    })
                }
        }, [])
    }

    return (
        <AsyncSelect
            name={index}
            getOptionValue={getOptionValue}
            getOptionLabel={(option) => (formElement.elementConfig.name === "organizations") && parent.authorizationDetails && parent.authorizationDetails.organizationId < 1000 && option.type  ? (option.label || option.name) + ' ('+option.type+')' : (option.label || option.name || option.prefix)}
            value={formElement.value}
            placeholder=""
            isClearable={isClearable}
            isMulti={multiSelect}
            isDisabled={isDisabled}
            closeMenuOnSelect={multiSelect ? false : true}
            cacheOptions={true}
            defaultOptions={defaultOptions}
            loadOptions={(inputValue) => useFetchMenu(inputValue)}
            onChange={handleSelectChange}
            onInputChange={(value) => handleSelectInputChange(value, index)}
    />
    );
}

Always getting invalid hook call error. I think calling fetchMenu hook from loadOptions is causing the error. But I couldn't find any fix so far.

Any help would be greatly appreciated.

Edit:

Solved my problem by moving out my code outside useEffects.

    const dispatch = useDispatch();
    const fetchMenu = (searchItem) => {
            if(!isEmpty(searchmenudetails)) {
                let menuDetails = generateMenuEndPoint(searchmenudetails, searchItem);

                return new Promise((resolve, reject) => {
                    dispatch(searchMenuAction(menuDetails, (response) => {
                        resolve(response[menuDetails.getData]);
                    }));
                })
            }
        }

I think useEffect is not required here.

Arjita Mitra
  • 962
  • 2
  • 13
  • 36
  • 1
    The [docs](https://reactjs.org/docs/hooks-rules.html) says to only call hooks at the top level, not in nested loops, functions or conditions. – robbannn Feb 04 '20 at 12:08
  • I know. So what is the solution here. how can I call my hook from loadOptions – Arjita Mitra Feb 04 '20 at 12:09
  • Like @robbannn said only call hooks at the top level, not in nested loops, functions or conditions. also fetchMenu can't be a react hook, you might want to revisit [Building Your Own Custom](https://reactjs.org/docs/hooks-custom.html). I also think there is a lot of missing information from your question for one to give you a code solution, so you might also want to add information on the problem you are trying to solve with your component – Chitova263 Feb 04 '20 at 13:01
  • @chitova263 *also fetchMenu can't be a react hook* . You said that because it's not starting with use? I have renamed it but didn't work. It won't work because I am calling it from loadOptions which violates top-level condition. I just wanted to make a reusbale component because the logic inside useEffect was getting repeated in each component I used select menu. Although I solved my problem by putting my code outside useEffect, still curious to know how to handle such a situation. Is it not possible to achieve with hooks? – Arjita Mitra Feb 04 '20 at 14:19

0 Answers0