skip to Main Content

I am trying to create a validation that automatically removes bad characters as they are typed in. The state is changing correctly and the removal is happening correctly. The problem I am having is updating the actual value of the input. I basically want to give the user a warning and then automatically remove the offending character.

I have this, which works:

const [domain, setDomain] = useState("http://example.com/");
const [url, setUrl] = useState("");

function handleSetUrl(e){
    const regExp = /^[A-Za-z0-9-_]+$/;
    if(e.match(regExp)){
        setUrl(e)
    }else{
        console.log("Your URL can only contain numbers, letters, dashes and underscores.");
        const modUrl = e.replace(/[^A-Za-z0-9-_]/g, '');
        setUrl(modUrl)
    }
}

And my input:

<p>{domain}{url}</p>
<Input
    label="Page URL"
    inputProps={{type: "text"}}
    defaultValue={url}
    onChange={(e) => handleSetUrl(e.target.value)}
/>

So when the user types in offending characters (for example / or a space) it removes the offending character and sets my state correctly –> setUrl(modUrl) and the constant url reflects that. The issue I am having is trying to update the <Input with the updated value. If I use defaultValue it doesn’t update when I remove the offending character using:

const modUrl = e.replace(/[^A-Za-z0-9-_]/g, '');
setUrl(modUrl)

And if I just use value={url} I am unable to edit the input at all. How do I get my input to reflect the change to setUrl in real time?

2

Answers


  1. Chosen as BEST ANSWER

    What I did was set value={url} and set a hook with useEffect to listen for a state change. Effectively it "acts" like defaultValue While updating the input in real time:

    <p>{domain}{url}</p>
    <Input
        label="Page URL"
        inputProps={{type: "text"}}
        value={url}
        onChange={(e) => handleSetUrl(e.target.value)}
    />
    

    And just added to following to my codeset:

    useEffect(() => {
        setUrl(url);
    });
    

  2. To update the input value in real time based on the modified URL, you can use the controlled component approach. Instead of using defaultValue, you can set the value prop of the component to the url state variable, and handle the input changes by updating the url state with the modified URL.

    const [domain, setDomain] = useState("http://example.com/");
    const [url, setUrl] = useState("");
    
    function handleSetUrl(e){
        const regExp = /^[A-Za-z0-9-_]+$/;
        if (e.match(regExp)) {
            setUrl(e);
        } else {
            console.log("Your URL can only contain numbers, letters, dashes, and underscores.");
            const modUrl = e.replace(/[^A-Za-z0-9-_]/g, '');
            setUrl(modUrl);
        }
    }
    
    return (
        <>
            <p>{domain}{url}</p>
            <Input
                label="Page URL"
                inputProps={{ type: "text" }}
                value={url} // Use the value prop to reflect the changes in real time
                onChange={(e) => handleSetUrl(e.target.value)}
            />
        </>
    );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search