У меня есть собственное приложение для реагирования. И у меня есть функция фильтра с использованием панели поиска из реакции-native-paper. Но удалить один символ в строке поиска невозможно.
Итак, вот контекст:
export const SearchAnimalContextProvider = ({ children }) => {
const [searchAnimal, setSearchAnimal] = useState([]);
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [input, setInput] = useState("");
const performSearch = async (text) => {
setLoading(true);
setError(null);
setTimeout(() => {
fetchAnimalData(text)
.then((response2) => {
setResults(response2);
setLoading(false);
})
.catch((err) => {
setLoading(false);
setError(err);
});
});
};
useEffect(() => {
setResults;
}, []);
return (
<SearchAnimalContext.Provider
value = {{
results,
setResults,
searchAnimal,
setSearchAnimal,
input,
setInput,
performSearch,
loading,
error,
}}>
{children}
</SearchAnimalContext.Provider>
);
};
А это функция панели поиска:
<Searchbar
placeholder = "Zoek een dier"
onChangeText = {(text) => {
if (searchTimer) {
clearTimeout(searchTimer);
}
if (text.length === 0) {
return null;
}
setInput(text[0].toUpperCase() + text.substring(1));
setSearchTimer(setTimeout(performSearch(text), 2000));
}}
value = {input}
/>
если я сделаю это так:
const performSearch = async (text) => {
setLoading(true);
setError(null);
setTimeout(() => {
fetchAnimalData(text)
.then((response2) => {
setResults(response2);
setLoading(false);
setInput();
})
.catch((err) => {
setLoading(false);
setError(err);
});
});
};
Затем я могу удалить последний символ. Но я получаю эту ошибку:
Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-com
Вопрос: как удалить один символ из панели поиска?
🤔 А знаете ли вы, что...
JavaScript может выполняться как на стороне клиента (в браузере), так и на стороне сервера (с использованием Node.js).
Проблема заключается в функции обработчика изменений onChangeText. Всякий раз, когда у вас есть текст внутри этой панели поиска, длина текста больше 0. Когда вы начинаете удалять текст, длина увеличивается до 1, и возникает ошибка - в коде есть условие if, которое проверяет «Является ли длина текста 0, и если да, то вернуть ноль". Я не знаю, в чем идея этого условия, но оно не позволяет установить состояние setInput с пустым строковым значением, из-за чего пользователь не может удалить текст отверстия. Я предлагаю удалить это условие if.
Обновлено: Поскольку вопрос был отредактирован, я хочу добавить информацию в свой комментарий - обычно появляется ошибка об изменении контролируемого ввода на неконтролируемый. В функции PerformSearch вы устанавливаетеInput(), что означает, что вы устанавливаете неопределенное значение во входном состоянии. Когда в качестве значения входного элемента передается значение null или неопределенное, ввод становится неконтролируемым. Предлагаю прочитать о контролируемых и неконтролируемых формах в официальной документации для лучшего понимания ошибки и концепции.
ВТОРОЕ РЕДАКТИРОВАНИЕ: Что касается ответа ОП о том, что когда он удалил оператор if, код не работает. Это потому, что в этом коде:
if (text.length === 0) {
return null;
}
setInput(text[0].toUpperCase() + text.substring(1));
Когда мы удаляем условие if, текст может быть пустой строкой, а text[0].toUpperCase() выдает ошибку, поскольку text[0] не определен. Решение с моей точки зрения следующее:
if (text.length === 0) {
setInput("")
// Add cleanup of the search result if necessary
return
}
setInput(text[0].toUpperCase() + text.substring(1));
Чтобы удалить один символ из строки, вам необходимо преобразовать строку в массив, отфильтровать символ, который вы хотите удалить, а затем снова собрать массив в строку. Вот как может выглядеть ваш код:
<Searchbar
placeholder = "Zoek een dier"
onChangeText = {(text) => {
if (searchTimer) {
clearTimeout(searchTimer);
}
if (!text.length) return null;
const removingAlphabet = 'a';
const arrayOfString = Array.from(text);
const filterArray = arrayOfString.filter(
(alphabet) =>
alphabet !== removingAlphabet &&
alphabet !== removingAlphabet.toUpperCase(),
);
const filteredString =
filterArray[0].toUpperCase() +
filterArray.substring(1).join("");
setInput(filteredString);
setSearchTimer(
setTimeout(() => performSearch(filteredString), 2000)
);
}}
value = {input}
/>