Search code examples
reactjsvalidationreact-hooksfetchreact-bootstrap

React how to make an input field with a fixed value combined with a dynamic value


Any solutions on how I can achieve similar results like this guy does with Javascript in React? Check link -> https://codepen.io/matheusls94/pen/WOdRPR

I have an inputfield/textfield(mui) which makes a post request to the server when a new user wants to register a new account/e-mail address. I want the user to avoid typing "@hotmail.com" which should be a fixed value that is uneditable/unremovable in the input field. Like in the codepen link above.

Dynamic value example -> Testemail, fixed value -> @hotmail.com

  const [email, setEmail]=useState("");

 async function Register(e){
    let item = {email};
    e.preventDefault();
    setLoading(true);

    let result = await fetch("https://localhost:44334/api/Register",{
        method:"POST",
        headers:{
            "Accept": "text/plain",
            "Content-Type": "application/json-patch+json",
        },
        body:JSON.stringify(item),
    });
    result = await result.json();

return (
<>
 <Container className="mt-5">
            <Row>
                <Col lg={4} md={6} sm={12} className="text-center mt-5 p-3">
                    <img className="icon-img" src={loginIcon} alt="icon"/>
                    <Form onSubmit={Register}>
                        <Form.Group>
                            <Form.Label>E-Mail</Form.Label>
                            <input value={dynamicvalue+fixedvalue} type="text" required={true} onChange={(e) => setEmail(e.target.value)}  fullWidth />
                        </Form.Group>
</>
)

Solution

  • You could append "@hotmail.com" to the value prop of the input and strip it out when updating state. Check if the input value ends with "@hotmail.com" and if it does allow the state to be updated.

    Example

    function App() {
      const [email, setEmail] = React.useState("");
    
      const changeHandler = (e) => {
        const { value } = e.target;
        if (value.endsWith("@hotmail.com")) {
          const modValue = value.replace("@hotmail.com", "");
          setEmail(modValue);
        }
      };
    
      return (
        <div className="App">
          <input
            type="text"
            value={`${email}@hotmail.com`}
            onChange={changeHandler}
          />
        </div>
      );
    }
    
    ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById("root")
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    <div id="root" />

    Update

    How would I achieve this if the values in modValue was to include "@hotmail.com" ? instead of replacing it with an empty string? For some reason the input value "@hotmail.com" does not get included on the registered user, only the dynamic value.

    Correct. You would need to append "@hotmail.com" back to the email value if using elsewhere.

    But you are correct, there's a way to initialize the email state "@hotmail.com" and do the same .endsWith test and state update without the string replace.

    function App() {
      const [email, setEmail] = React.useState("@hotmail.com");
    
      const changeHandler = (e) => {
        const { value } = e.target;
        if (value.endsWith("@hotmail.com")) {
          setEmail(value);
        }
      };
    
      return (
        <div className="App">
          <input
            type="text"
            value={email}
            onChange={changeHandler}
          />
        </div>
      );
    }
    
    ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById("root")
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
    <div id="root" />