Как установить значение для события с помощью автозаполнения React

#reactjs #material-ui #autosuggest

Вопрос:

У меня есть этот экран [![Экран][1]][1], на котором я могу искать бизнес с помощью автозаполнения (поддерживается автозаполнением Google maps). Если пользователь вводит Ввод текста, который не был предложен placeAutoComplete, сервер выбирает опцию поиска текста на картах и отображает результаты на карте.

Теперь моя проблема в том, что, когда пользователь нажимает на место на карте, я хочу, чтобы название этого места отображалось в режиме самовнушения.

Я изо всех сил пытаюсь понять, как привязать значение только тогда, когда оно выбрано (из внешнего события)

Естественно, я попытался установить значение (если оно равно нулю, пока нет выбора): я получаю эту ошибку

 VM11047 react_devtools_backend.js:2560 Material-UI: A component is changing the uncontrolled value state of Autocomplete to be controlled.
Elements should not switch from uncontrolled to controlled (or vice versa).
Decide between using a controlled or uncontrolled Autocomplete element for the lifetime of the component.
The nature of the state is determined during the first render, it's considered controlled if the value is not `undefined`.
 

Мой код очень прост, я не знаю, стоит ли им делиться:

EntityAutocomplete.js

 import React, {useState} from 'react';
import TextField from '@material-ui/core/TextField';
import Autocomplete from '@material-ui/lab/Autocomplete';
import {useTranslation} from "next-i18next";
import {useRouter} from "next/router";
import {REGION_LIST, PLACE_CANDIDATE_LIST} from "../../../constants/graphQueries";
import {useQuery} from "@apollo/client";
import logger from "../../../lib/logger";
import {defaultIfNull} from "../../../constants/util";

export default function EntityAutocomplete(props) {
    const [value, setValue] = useState();
    const [searchText, setSearchText] = useState([]);
    const [options, setOptions] = useState([]);
    const [loadingTextSearch, setLoadingTextSearch] = useState(true);

    const {t} = useTranslation()
    const router = useRouter()

    const isSearchEmpty = searchText.length == 0 || searchText.trim().length == 0;
    const {loading, data, error} = useQuery(REGION_LIST, {
        variables: {name: searchText}, onCompleted: onServerResponse, skip: isSearchEmpty
    })
    // triggered if a text was entered manually (not from list)
    const {loadingMarkers, markersData, markerSearchError} = useQuery(PLACE_CANDIDATE_LIST, {
        variables: {name: searchText},
        onCompleted: onTextSearchResponse,
        skip: !loadingTextSearch,
        fetchPolicy: "no-cache",
        notifyOnNetworkStatusChange: true
    })
    // disable trigger just after executing the request

    if (loading) {
        // logger.debug("loading")
    }
    if (error) {
        logger.info("error: ", error)
    }

    function onServerResponse(data) {
        if (data) {
            setOptions(data.locationMany);
        }
    }

    function onTextSearchResponse(data) {
        const {onMarkersChanged} = props
        if (data) {
            const locationCandidateMany = data.locationCandidateMany;
            if (onMarkersChanged)
                onMarkersChanged(locationCandidateMany)
            //must be placed here otherwise this callback is not called if disabled before response
            if (loadingTextSearch)
                setLoadingTextSearch(false)

        }
    }

    function valueChanged(event, newValue) {
        setValue(newValue);
        const onEntitySelected = props.onEntitySelected;
        if (isAutoSuggestion(newValue)) {
            if (onEntitySelected != null)
                onEntitySelected(value)
            return
        }
        //text was typed with enter: find matching results
        setLoadingTextSearch(true)
    }

    function isAutoSuggestion(option) {
        return option?.source != null;
    }

    function getOptionLabel(option) {
        return isAutoSuggestion(option) ? option.name : option;
    }

    return (
        <Autocomplete
            value={props.selected}
            freeSolo
            onChange={valueChanged}
            onInputChange={(e, value) => {
                setSearchText(value)
            }}
            options={options}
            getOptionLabel={getOptionLabel}
            disableClearable
            renderInput={(params) => (
                <TextField
                    {...params}
                    label={t(`service.search.placeholder`)}
                    margin="normal"
                    variant="outlined"
                    InputProps={{...params.InputProps, type: 'search'}}
                />
            )}
        />
    );
}
 

И родительский компонент называет это так:

     <Grid item className={classes.entitySelector}>
        <EntityAutocomplete label={t(`common.entityHome.selectEntity.entityLabel`)}
                            entityName={issue.entity?.name} onEntitySelected={onPlaceSelected}
                            onSelectedEntityInfoLoaded={onSelectedEntityInfoLoaded}
                            onMarkersChanged={setMarkers} selected={selectedPlace}/>
    </Grid>
 

Я также попытался добавить эффект, чтобы оставить доступным только один параметр, если select он не равен нулю:

const {selected} = props
useEffect(() => {
if (selected != null) {
setOptions([selected])
}
}, [selected])

but it doesn’t work
[1]: https://i.stack.imgur.com/t3dhG.png