StoneForest
StoneForest

Reputation: 25

React useState initialise with an existing object

I'm new to React and don't know if this is allowed in React:

I want to collect form data and send requests with such data in a modal.

I also want the input fields to have default values from existing data (props.itemInfo).

I'm trying to initialise the formData with

function Parent() {
  const [state, setState] = useState(false);
  const [itemInfo, setItemInfo] = useState({})

  // itemInfo get from somewhere in the middle

  return (
    <div>
      <button onClick={() => setState(true)> Render modal </button>
      <Modal itemInfo={itemInfo} state={state} setState={setState} /> 
    </div>
  )
};


function Modal(props) {
  let itemInfo = props.itemInfo;
  console.log(typeof itemInfo); // 1
  console.log(itemInfo);        // 2

  /* I also tried 
    const [formData, setFormData] = useState({itemInfo});
    but not working
  */

  const [formData, setFormData] = useState({
    itemID: itemInfo.itemID,
    userID: itemInfo.userID,
    isActive: itemInfo.isActive,
    purchaseCost: itemInfo.purchaseCost,
    dateModified: itemInfo.dateModified,
    dateCreated: itemInfo.dateCreated,
    description: itemInfo.description,
    itemGrouping: itemInfo.itemGrouping,
  });
  console.log(itemInfo.itemID); // 3
  console.log(formData.itemID); // 4

  const handleCloseModal = () => {
    props.setState(false);
  };

  const handleFormChange = (e) => {
    const { id, value } = e.target;
    setFormData((prevState) => ({
      ...prevState,
      [id]: value,
    }));
  };
  const handleSubmit = (e) => {
    e.preventDefault();
    // send request with formData
  };
  return (
    <ReactModal isOpen={props.state} ariaHideApp={false}>
      <form id="login">
        <div>
          <label>Grouping: </label>
          <input
            id="grouping"
            type="text"
            defaultValue={formData.itemGrouping}
            onChange={handleFormChange}
            required
          />
        </div>
        <div>
          <label>Cost: </label>
          <input
            id="cost"
            type="text"
            defaultValue={formData.purchaseCost}
            onChange={handleFormChange}
            required
          />
        </div>
        <div>
          <label>Description: </label>
          <input
            id="description"
            type="text"
            defaultValue={formData.description}
            onChange={handleFormChange}
            required
          />
        </div>
        <button type="submit" onClick={handleSubmit}>
          Submit
        </button>
      </form>
      <button onClick={handleCloseModal}>Close Modal</button>
    </ReactModal>
  );
}

The existing object received is

{
    "itemID": 3,
    "userID": 2,
    "isActive": 1,
    "purchaseCost": 0,
    "dateModified": "2022-10-05 03:44:07",
    "dateCreated": "2022-10-05",
    "description": "Gift from my sister for my 29th birthday!",
    "itemGrouping": null
}

and the 4 console.log() gives the following output:

object        // 1

{
    "itemID": 3,
    "userID": 2,
    "isActive": 1,
    "purchaseCost": 0,
    "dateModified": "2022-10-05 03:44:07",
    "dateCreated": "2022-10-05",
    "description": "Gift from my sister for my 29th birthday!",
    "itemGrouping": null
}              // 2

3              // 3

undefined      // 4

I don't know why this is not working, and is there any approach that can achieve the goal I want.

Thanks

Upvotes: 0

Views: 314

Answers (1)

Vicky Ahuja
Vicky Ahuja

Reputation: 1204

There is an issue with storing the prop itemInfo inside the state value.

You are storing the object in a new object like,

const [formData, setFormData] = useState({itemInfo});

It will create a state with itemInfo property, So after using this, You will only be able to access the state by following statements,

formData.itemInfo.itemID

This is JavaScript where if you add an object by its name in the new object it will add new property similar to the object name and value with the placed object.

You can also simply store the prop item in a state like below,

const [formData, setFormData] = useState({ ...itemInfo });

The above statement will extract all the object properties into the new object, and can be accessible by formData state.

Upvotes: 1

Related Questions