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 thinklocalStorage
will fail to save 12 - 15 MB of data. There must be another way to store huge data inReact/TypeScript
?Change/improve the
onChange
event, so it will only triggerAPI
request when a user finished typing and get the full city word instead of calling request on every character. Is it possible to override theonChange
event?
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
setTimeout
function 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.