1

I am creating Dynamic input fields I am validating some required fields my validated output in the array I try to show error values in input I cause some errors. I tried an some match with an index array but i not working

codeSandbox :https://codesandbox.io/s/floral-bash-lrvkc?file=/src/App.js:0-2399

thanks for Help

import React, { useState } from "react";
import "./styles.css";

function App() {
  const [inputList, setInputList] = useState([{ firstName: "", lastName: "" }]);
  const [formError, setFormError] = useState([]);
  const [isSubmit, setisSubmit] = useState(false);

  // handle input change
  const handleInputChange = (e, index) => {
    const { name, value } = e.target;
    const list = [...inputList];
    list[index][name] = value;
    setInputList(list);
  };

  // handle click event of the Remove button
  const handleRemoveClick = (index) => {
    const list = [...inputList];
    list.splice(index, 1);
    setInputList(list);
  };

  // handle click event of the Add button
  const handleAddClick = () => {
    setInputList([...inputList, { firstName: "", lastName: "" }]);
  };
  const Submit = (e) => {
    e.preventDefault();
    const errorMsg = inputList.map((list, key) => {
      let error = {};
      if (!list.firstName) {
        error.errorfirstName = "FirstName is required";
      } else {
        error.errorfirstName = "";
      }
      if (!list.lastName) {
        error.errorlastName = "LastName is required";
      } else {
        error.errorlastName = "";
      }
      return error;
    });
    console.log(errorMsg);
    setFormError(errorMsg);
  };

  return (
    <div className="App">
      {inputList.map((x, i) => {
        return (
          <div className="box">
            <input
              name="firstName"
              placeholder="Enter First Name"
              value={x.firstName}
              onChange={(e) => handleInputChange(e, i)}
            />
            <input
              className="ml10"
              name="lastName"
              placeholder="Enter Last Name"
              value={x.lastName}
              onChange={(e) => handleInputChange(e, i)}
            />
            <div className="btn-box">
              {inputList.length !== 1 && (
                <button className="mr10" onClick={() => handleRemoveClick(i)}>
                  Remove
                </button>
              )}
              {inputList.length - 1 === i && (
                <button onClick={handleAddClick}>Add</button>
              )}
            </div>
          </div>
        );
      })}
      <button onClick={Submit}>Submit</button>
      <div style={{ marginTop: 20 }}>{JSON.stringify(inputList)}</div>
    </div>
  );
}

export default App;
Gokul
  • 187
  • 3
  • 11

2 Answers2

2

Please see the below code. I have added some code - see comments marked by // CHANGE HERE

import React, { useState } from "react";
import "./styles.css";

function App() {
  const [inputList, setInputList] = useState([{ firstName: "", lastName: "" }]);
  const [formError, setFormError] = useState([]);
  const [isSubmit, setisSubmit] = useState(false);

  // handle input change
  const handleInputChange = (e, index) => {
    const { name, value } = e.target;
    const list = [...inputList];
    list[index][name] = value;
    setInputList(list);
  };

  // handle click event of the Remove button
  const handleRemoveClick = (index) => {
    const list = [...inputList];
    list.splice(index, 1);
    setInputList(list);
  };

  // handle click event of the Add button
  const handleAddClick = () => {
    setInputList([...inputList, { firstName: "", lastName: "" }]);
  };

  // CHANGE HERE: a flag to be set when there is an error
  var isError = false;

  const Submit = (e) => {
    e.preventDefault();
    const errorMsg = inputList.map((list, key) => {
      let error = {};
      if (!list.firstName) {
        error.errorfirstName = "FirstName is required";
        // CHANGE HERE: set error flag
        isError = true;
      } else {
        error.errorfirstName = "";
      }
      if (!list.lastName) {
        error.errorlastName = "LastName is required";
        // CHANGE HERE: set error flag
        isError = true;
      } else {
        error.errorlastName = "";
      }
      return error;
    });
    console.log(errorMsg);
    setFormError(errorMsg);
    // CHANGE HERE: return false and prevent form submission in case of errors
    if (isError)
      return false;
  };

  // CHANGE HERE: added Error function
  const Error = () => {
    return <>
      {formError.map((error, i) => {
        var str = error.errorfirstName + " " + error.errorlastName;
        if (str !== ' ')
          return <p key={i.toString()}> {i} {str}</p>;
        return <></>
      })}
    </>;
  };

  return (
    <div className="App">
      {inputList.map((x, i) => {
        return (
          <div className="box">
            <input
              name="firstName"
              placeholder="Enter First Name"
              value={x.firstName}
              onChange={(e) => handleInputChange(e, i)}
            />
            <input
              className="ml10"
              name="lastName"
              placeholder="Enter Last Name"
              value={x.lastName}
              onChange={(e) => handleInputChange(e, i)}
            />
            <div className="btn-box">
              {inputList.length !== 1 && (
                <button className="mr10" onClick={() => handleRemoveClick(i)}>
                  Remove
                </button>
              )}
              {inputList.length - 1 === i && (
                <button onClick={handleAddClick}>Add</button>
              )}
            </div>
          </div>
        );
      })}
      <button onClick={Submit}>Submit</button>
      // CHANGE HERE: show an error if any
      <Error />
      <div style={{ marginTop: 20 }}>{JSON.stringify(inputList)}</div>
    </div>
  );
}

export default App;
kiner_shah
  • 3,939
  • 7
  • 23
  • 37
0

Form above the answer I made some changes

import React, { useState } from "react";
import "./styles.css";

function App() {
  const [inputList, setInputList] = useState([{ firstName: "", lastName: "" }]);
  const [formError, setFormError] = useState([]);
  const [isSubmit, setisSubmit] = useState(false);

  // handle input change
  const handleInputChange = (e, index) => {
    const { name, value } = e.target;
    const list = [...inputList];
    list[index][name] = value;
    setInputList(list);
  };

  // handle click event of the Remove button
  const handleRemoveClick = (index) => {
    const list = [...inputList];
    list.splice(index, 1);
    setInputList(list);
  };

  // handle click event of the Add button
  const handleAddClick = () => {
    setInputList([...inputList, { firstName: "", lastName: "" }]);
  };

  // CHANGE HERE: a flag to be set when there is an error
  var isError = false;

  const Submit = (e) => {
    e.preventDefault();
    const errorMsg = inputList.map((list, key) => {
      let error = {};
      if (!list.firstName) {
        error.errorfirstName = "FirstName is required";
        // CHANGE HERE: set error flag
        isError = true;
      } else {
        error.errorfirstName = "";
      }
      if (!list.lastName) {
        error.errorlastName = "LastName is required";
        // CHANGE HERE: set error flag
        isError = true;
      } else {
        error.errorlastName = "";
      }
      return error;
    });
    console.log(errorMsg);
    setFormError(errorMsg);
    // CHANGE HERE: return false and prevent form submission in case of errors
    if (isError) return false;
  };

  return (
    <div className="App">
      {inputList.map((x, i) => {
        return (
          <div className="box">
            <div>
              <input
                name="firstName"
                placeholder="Enter First Name"
                value={x.firstName}
                onChange={(e) => handleInputChange(e, i)}
              />
              {formError.map((error, index) => (
                <p key={index.toString()}>
                  {i == index ? (
                    <>
                      {index}
                      {error.errorfirstName}{" "}
                    </>
                  ) : null}
                </p>
              ))}
            </div>
            <div>
              <input
                className="ml10"
                name="lastName"
                placeholder="Enter Last Name"
                value={x.lastName}
                onChange={(e) => handleInputChange(e, i)}
              />
              {formError.map((error, index) => (
                <p key={index.toString()}>
                  {i == index ? (
                    <>
                      {index}
                      {error.errorlastName}{" "}
                    </>
                  ) : null}
                </p>
              ))}
            </div>
            <div className="btn-box">
              {inputList.length !== 1 && (
                <button className="mr10" onClick={() => handleRemoveClick(i)}>
                  Remove
                </button>
              )}
              {inputList.length - 1 === i && (
                <button onClick={handleAddClick}>Add</button>
              )}
            </div>
          </div>
        );
      })}
      <button onClick={Submit}>Submit</button>
    </div>
  );
}

export default App;
Gokul
  • 187
  • 3
  • 11
  • As best practice, you should refrain from using `index` for your `key` values as this can lead to unexpected behaviour. [See reference](https://stackoverflow.com/a/56781201/4433536) – 0xe1λ7r Nov 29 '21 at 05:27