I use Autosuggest component (https://github.com/moroshko/react-autosuggest) in my React website. So, on the onChange event, I call serviceOsago to get the city/region/country data. Full data are too heavy to load at once, it takes about 10 seconds, so I get it partially by using onChange event. But the problem is when I type a city name for example: "Стрий", it does not add it to the Autosuggest and does not display it.
const onChange = (event, {newValue, method}) => {
setValue(newValue);
serviceOsago.getCityCode(newValue).then((value:any) => {
setCities(value);
});
};
When debugging it in the browser (Network -> Fetch/XHR), I found out it fails to add "Стрий" to Autosuggest due to request delay. For example, when I typed "Стрий", it still loads the "Стри" old call.
Code:
import React, { useState } from 'react';
import Autosuggest from 'react-autosuggest';
import {useDispatch, useSelector} from 'react-redux';
import {
getErrorCity,
getLoadingCity,
getRegisterCity,
setData,
setError
} from '../../../redux-data/city/cityReducer';
import {getInstanceError} from '../../../utils/getInstanceError';
import theme from './AutoComplete.module.css';
import SquareLoader from 'react-spinners/SquareLoader';
import {config} from '../../../assets/config';
import serviceOsago from '../../../service/serviceOsago';
export const AutoComplete = (props) => {
const [touch, setTouch] = useState(false);
const dispatch = useDispatch();
const regCity = useSelector(getRegisterCity);
const loading = useSelector(getLoadingCity);
const [suggestions, setSuggestions] = useState([] as any[]);
const [value, setValue] = useState(regCity);
const [cities, setCities] = useState([]);
const getSuggestions = (value, cities) => {
let res = [];
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
if (inputValue && inputLength > 0) {
res = cities.filter(city => {
return city.name.trim().toLowerCase().startsWith(inputValue);
});
}
return res;
};
const renderSuggestion = suggestion => (
<div>
{suggestion.nameFull}
</div>
);
const getSuggestionValue = suggestion => suggestion.nameFull;
const error = useSelector(getErrorCity);
const errors = {
regCity: error
};
const {
getClassError,
getMessageError
} = getInstanceError(errors);
const mes = getMessageError('regCity');
const onSuggestionsFetchRequested = ({ value }) => {
setSuggestions(getSuggestions(value, cities));
};
const onChange = (event, {newValue, method}) => {
setValue(newValue);
console.log(newValue);
serviceOsago.getCityCode(newValue).then((value:any) => {
setCities(value);
});
};
const onBlur = () => {
setTouch(true);
if (value === '') {
dispatch(setError({
message: 'Це поле обов\'язкове'
}));
}
};
const inputProps = {
placeholder: 'Місто реєстрації автомобіля',
value,
onChange,
onBlur,
disabled: loading,
id: props.id
};
const renderSuggestionInput = (inputProps) => (
props.isAutoFocus ? <input {...inputProps} autoFocus /> : <input {...inputProps} />
);
const onSuggestionHighlighted = ({ suggestion }) => {
//console.log(suggestion);
};
return (
<div className={getClassError('regCity', touch)}>
<Autosuggest
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
onSuggestionSelected={(event, data) => {
dispatch(setData(data.suggestion));
}}
theme={theme}
renderInputComponent={renderSuggestionInput}
highlightFirstSuggestion={true}
alwaysRenderSuggestions={true}
onSuggestionHighlighted={onSuggestionHighlighted}
/>
{mes && <p>{mes}</p>}
<SquareLoader loading={loading} size={20} color={config.color} css={config.css}/>
</div>
);
};
I think, there are two options how to fix this issue.
Load full data when website is loaded, save somewhere this data (for example:
localStorage) and add it toAutosuggest, so it will be available when user is typing. But I thinklocalStoragewill fail to save 12 - 15 MB of data. There must be another way to store huge data inReact/TypeScript?Change/improve the
onChangeevent, so it will only triggerAPIrequest when a user finished typing and get the full city word instead of calling request on every character. Is it possible to override theonChangeevent?
What is the proper way to add data from REST API to Autosuggest when a user typing data in React/TypeScript? Thank you.
Top comments (1)
Ok. I have fixed this issue by using
setTimeoutfunction anduseEffect.This will allow to intercept the user typing and send request only after 1 second. Now, it works well. This issue is resolved. Thank you.