Как удалить один символ из состояния в реакции библиотеки?

У меня есть собственное приложение для реагирования. И у меня есть функция фильтра с использованием панели поиска из реакции-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).


90
2

Ответы:

Решено

Проблема заключается в функции обработчика изменений 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}
/>