skip to Main Content

I have a react native app. And I have some filter function using the Searchbar from react-native-paper. But deleting a single character in the Searchbar is not possible.

So this is the context:

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>
    );
};

And this is the Searchbar function:

            <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}
            />

if I do it like:

    const performSearch = async (text) => {
        setLoading(true);
        setError(null);
        setTimeout(() => {
            fetchAnimalData(text)
                .then((response2) => {
                    setResults(response2);
                    setLoading(false);
                    setInput();
                })
                .catch((err) => {
                    setLoading(false);
                    setError(err);
                });
        });
    };

Then I can remove the last character. But I get this error:

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

Question: how to remove a single character from the Searchbar?

2

Answers


  1. The problem is in change handler function onChangeText. Whenever you have some text inside that Searchbar, the length of the text is greater than 0. When you start to delete the text, the length is going until 1 and there is the bug – the code have if condition, which checks "Is the length of the text 0 and if it is, then return null". I do not know what is the idea of this condition, but it prevents to setInput state with empty string value, for that the user can’t delete the hole text. I suggest to remove that if condition.

    EDIT: Since the question was edited, I want to add info in my comment – it is normally to receive the error about changing controlled input to uncontrolled. In function performSearch you setInput() which means you set undefined value in input state. When there is null or undefined passed as value to input element, the input become uncontrolled. I suggest to read about controlled and uncontrolled forms in the official documentation for better understanding of the error and concept.

    Login or Signup to reply.
  2. To delete a single character from a string, you need to convert the string into an array, filter out the character you want to remove, and then reassemble the array back into a string. Here’s how your code might look:

    <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(),
          );
    
          setInput(
            filterArray[0].toUpperCase() +
            filterArray.substring(1).join("")
          );
    
          setSearchTimer(
            setTimeout(() => performSearch(filteredString), 2000)
          );
      }}
      value={input}
    />
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search