Home > Blockchain >  Update state for a React Object
Update state for a React Object

Time:03-30

I wanted to change the value for app_id to Hello World during handleChange using state hooks. However I am not able to update the state for app_id and didn't find a way to update the value for app_id before submitting the form.

To further clarify, app_id is a dropdown and has a custom option. When the custom option is selected I want the value for app_id to be picked from the custom text box before submitting the form. For this, I was trying to replace the previous value in app_id with the value of custom_app_id (Text Box).

import './App.css';
import 'bootstrap/dist/css/bootstrap.css';
import { useState , useEffect } from "react";
import { Container, Button, Form  } from "react-bootstrap";

function App() {
  const initialValues = { username:"" , email: "", password: "", account_id: "", app_id:"", custom_app_id:""};
  const [formValues, setFormValues] = useState(initialValues);
  const [formErrors, setFormErrors] = useState({});
  const [isSubmit, setIsSubmit] = useState(false);
  const handleChange = (e) => {
    const { id, value } =e.target;
    if (document.getElementById("app_id").value != "custom"){
      document.getElementById("custom_app_id").disabled = true;
    }
    if (document.getElementById("app_id").value === "custom"){
      document.getElementById("custom_app_id").disabled = false;
      console.log(document.getElementById("app_id").value);
      // initialValues["app_id"] =  document.getElementById("custom_app_id").value;
      setFormValues(prevState => ({
        ...prevState,
        ["app_id"]: "Hello World"
    }));
    }
    setFormValues({ ...formValues, [id]: value });
    console.log(formValues);
  };
  const handleSubmit = (e) => {
    e.preventDefault();
    setFormErrors((validate(formValues)));
    setIsSubmit(true);
  };
  useEffect(()=>{
    console.log(formErrors)
    if(Object.keys(formErrors).length === 0 && isSubmit){
      console.log(formValues);
    }
  }, [formErrors]);
  const validate = (values) => {
    const errors = {};
    var numcheck = /^[0-9\b] $/;
    if( !values.username){
      errors.username = "Username is required"
    }
    if( !values.email){
      errors.email = "Email is required"
    }
    if( !values.password){
      errors.password = "Password is required"
    }
    if(  numcheck.test(values.account_id) === false ){
      errors.account_id = "Account ID should only have numbers and cannot be empty"
    }
    if( !values.app_id){
      errors.app_id = "App ID is required"
    }
    return errors;
  };



  return (
    <div style={{  display: "block", width: 1000, padding: 30 }}>
    <h4>Self Service UI - Version 2.0</h4>
    <pre> { JSON.stringify(formValues)}</pre>
    <Container>
    <Form onSubmit = {handleSubmit}>
      <Form.Group>
        <Form.Label>Username:</Form.Label>
        <Form.Control id="username" type="text" placeholder="Enter your username" value={formValues.username} onChange={handleChange} />
        <p style={{ color: 'red' }}>{formErrors.username}</p>
      </Form.Group>
      <Form.Group>
        <Form.Label>Enter your email address:</Form.Label>
        <Form.Control id="email" type="email" placeholder="Enter your your email address" value={formValues.email} onChange={handleChange} />
        <p style={{ color: 'red' }}>{formErrors.email}</p>
      </Form.Group>
      <Form.Group>
        <Form.Label>Enter your password:</Form.Label>
        <Form.Control id="password" type="password" placeholder="Enter your password" value={formValues.password} onChange={handleChange} />
        <p style={{ color: 'red' }}>{formErrors.password}</p>
      </Form.Group>
      <Form.Group>
            <Form.Label>account_id</Form.Label>
            <Form.Control
              id="account_id"
              type="text"
              placeholder="This is typically 9 digits"
              value={formValues.account_id}
              onChange={handleChange}
            />
             <p style={{ color: 'red' }}>{formErrors.account_id}</p>
      </Form.Group>

      <Form.Group>
            <Form.Label>app_id</Form.Label>
            <Form.Control
              as="select"
              className="custom-select"
              id="app_id"
              value={formValues.app_id}  
              onChange={handleChange}
             >
              <option value="" hidden>This is typically 3 characters.</option>
              <option value="cs">contentserv</option>
              <option value="ew">enterworks</option>
              <option value="ep">epcc</option>
              <option value="gms">gms</option>
              <option value="iu">internal-use</option>
              <option value="is">intershop</option>
              <option value="mag">magento</option>
              <option value="oc">oracle-commerce</option>
              <option value="stb">stibo</option>
              <option value="nat">natalie</option>
              <option value="custom">Custom/Others</option>
            </Form.Control>
            <p style={{ color: 'red' }}>{formErrors.app_id}</p>
      </Form.Group>

      <Form.Group>
            <Form.Label>custom_app_id</Form.Label>
            <Form.Control
              placeholder="This is typically 3 characters."
              id="custom_app_id"
              disabled="disabled"
              type="text"
              value={formValues.custom_app_id}
              onChange={handleChange}
            />
      </Form.Group> 
      <Button variant="primary" type="submit">
        Click here to submit form
      </Button>
    </Form>
    </Container>
  </div>
  );
}

export default App;

CodePudding user response:

Disclaimer: This is not "react" code that I would personally develop. It is essentially a copy of OP's question as-is with only one minor change.

The assumed objective: When submitting the form, use custom_app_id when user has selected "custom" from the dropdown. If else, use the app_id as-is.

Please look at the second <pre></pre> tag to see how one is able to pick the appropriate value.

Code Snippet

Please use FULL PAGE to view the code demo clearly

//import './App.css';
//import 'bootstrap/dist/css/bootstrap.css';
const { useState , useEffect } = React;
// import { Container, Button, Form  } from "react-bootstrap";
const { Container, Button, Form  } = ReactBootstrap;

function App() {
  const initialValues = { username:"" , email: "", password: "", account_id: "", app_id:"", custom_app_id:""};
  const [formValues, setFormValues] = useState(initialValues);
  const [formErrors, setFormErrors] = useState({});
  const [isSubmit, setIsSubmit] = useState(false);
  const handleChange = (e) => {
    const { id, value } =e.target;
    if (document.getElementById("app_id").value != "custom"){
      document.getElementById("custom_app_id").disabled = true;
    }
    if (document.getElementById("app_id").value === "custom"){
      document.getElementById("custom_app_id").disabled = false;
      // console.log(document.getElementById("app_id").value);
      // initialValues["app_id"] =  document.getElementById("custom_app_id").value;
      setFormValues(prevState => ({
        ...prevState,
        ["app_id"]: "Hello World"
    }));
    }
    setFormValues({ ...formValues, [id]: value });
    // console.log(formValues);
  };
  const handleSubmit = (e) => {
    e.preventDefault();
    setFormErrors((validate(formValues)));
    setIsSubmit(true);
  };
  useEffect(()=>{
    //console.log(formErrors)
    if(Object.keys(formErrors).length === 0 && isSubmit){
      //console.log(formValues);
    }
  }, [formErrors]);
  const validate = (values) => {
    const errors = {};
    var numcheck = /^[0-9\b] $/;
    if( !values.username){
      errors.username = "Username is required"
    }
    if( !values.email){
      errors.email = "Email is required"
    }
    if( !values.password){
      errors.password = "Password is required"
    }
    if(  numcheck.test(values.account_id) === false ){
      errors.account_id = "Account ID should only have numbers and cannot be empty"
    }
    if( !values.app_id){
      errors.app_id = "App ID is required"
    }
    return errors;
  };



  return (
    <div style={{  display: "block", width: 1000, padding: 30 }}>
    <h4>Self Service UI - Version 2.0</h4>
    <pre> { JSON.stringify(formValues)}</pre>
    <pre> Use app_id: {formValues.app_id === 'custom' ? formValues.custom_app_id : formValues.app_id} </pre>
    <Container>
    <Form onSubmit = {handleSubmit}>
      <Form.Group>
        <Form.Label>Username:</Form.Label>
        <Form.Control id="username" type="text" placeholder="Enter your username" value={formValues.username} onChange={handleChange} />
        <p style={{ color: 'red' }}>{formErrors.username}</p>
      </Form.Group>
      <Form.Group>
        <Form.Label>Enter your email address:</Form.Label>
        <Form.Control id="email" type="email" placeholder="Enter your your email address" value={formValues.email} onChange={handleChange} />
        <p style={{ color: 'red' }}>{formErrors.email}</p>
      </Form.Group>
      <Form.Group>
        <Form.Label>Enter your password:</Form.Label>
        <Form.Control id="password" type="password" placeholder="Enter your password" value={formValues.password} onChange={handleChange} />
        <p style={{ color: 'red' }}>{formErrors.password}</p>
      </Form.Group>
      <Form.Group>
            <Form.Label>account_id</Form.Label>
            <Form.Control
              id="account_id"
              type="text"
              placeholder="This is typically 9 digits"
              value={formValues.account_id}
              onChange={handleChange}
            />
             <p style={{ color: 'red' }}>{formErrors.account_id}</p>
      </Form.Group>

      <Form.Group>
            <Form.Label>app_id</Form.Label>
            <Form.Control
              as="select"
              className="custom-select"
              id="app_id"
              value={formValues.app_id}  
              onChange={handleChange}
             >
              <option value="" hidden>This is typically 3 characters.</option>
              <option value="cs">contentserv</option>
              <option value="ew">enterworks</option>
              <option value="ep">epcc</option>
              <option value="gms">gms</option>
              <option value="iu">internal-use</option>
              <option value="is">intershop</option>
              <option value="mag">magento</option>
              <option value="oc">oracle-commerce</option>
              <option value="stb">stibo</option>
              <option value="nat">natalie</option>
              <option value="custom">Custom/Others</option>
            </Form.Control>
            <p style={{ color: 'red' }}>{formErrors.app_id}</p>
      </Form.Group>

      <Form.Group>
            <Form.Label>custom_app_id</Form.Label>
            <Form.Control
              placeholder="This is typically 3 characters."
              id="custom_app_id"
              disabled="disabled"
              type="text"
              value={formValues.custom_app_id}
              onChange={handleChange}
            />
      </Form.Group> 
      <Button variant="primary" type="submit">
        Click here to submit form
      </Button>
    </Form>
    </Container>
  </div>
  );
}


ReactDOM.render(
  <div>
    DEMO
    <App />
  </div>,
  document.getElementById("rd")
);
<div id="rd"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/react/umd/react.production.min.js" crossorigin></script>

<script
  src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"
  crossorigin></script>

<script
  src="https://unpkg.com/react-bootstrap@next/dist/react-bootstrap.min.js"
  crossorigin></script>

Explanation

95% of the code is from the question as-is. Only changes made are to make it a working-demo within stack-snippets. And, the second pre-tag which shows how one is able to pick the necessary value from formValues.

CodePudding user response:

Thanks Everyone, I figured out a solution for this by directly assigning values to formValues.app_id in handleChange function. Here is my change (Rest of the code is same as it is):

 const handleChange = (e) => {
    const { id, value } =e.target;
    if(id === "app_id" && value === "custom"){
      document.getElementById("custom_app_id").disabled = false;
    }
    if(id === "app_id" && value !== "custom"){
      document.getElementById("custom_app_id").disabled = true;
    }
    if(id === "custom_app_id" && value !== ""){
      formValues.app_id = document.getElementById("custom_app_id").value
      console.log(formValues.app_id);
    }
    setFormValues({ ...formValues, [id]: value });
    console.log(formValues);
  };

  • Related