Home > Software engineering >  event.target in undefined in React <input> component
event.target in undefined in React <input> component

Time:10-29

I am using React. I am trying to dynamically add and remove input fields. I am trying to make a list of objects like


    [
    {"item": 1, "key": "RAM", "value": "8GB"},
    {"item": 1, "key": "Color", "value": "Black"},
    {"item": 1, "key": "Used For", "value": "6 months"},
    ]

There can be any number of objects in the above list. I want to send a post request with the above data. The problem I am facing is creating the above pattern. I want to create an Add button which will show two input fields for the key and value side by side. Then I want to add them to the above list when the user enters the values. Don't worry about the item because it is always the same.Here is a CodeSandBox link. Please expand the browser tab in CodeSandBox to see the full page.

I have done the following:

App.js


    import React, { useState } from "react";
    import {
      SpecificationFormContainer,
      SpecificationFormCard,
      SpecificationFormTitle,
      SpecificationInputRow,
      SpecificationValue,
      AddMoreButton,
      RemoveButton
    } from "./Elements";
    import "./styles.css";
    
    export default function App() {
      const [numberOfSpecFields, setNumberOfSpecFields] = useState(0);
      const [specificationKeys, setSpecificationKeys] = useState("");
      const [specificationValues, setSpecificationValues] = useState("");
      const [specifications, setSpecifications] = useState([]);
    
      const handleSpecKeyChange = (event) => {
        setSpecificationKeys(event.target.value);
      };
    
      const handleSpecValueChange = (event) => {
        setSpecificationValues(event.target.value);
      };
    
      const handleFocusOut = (event, index) => {
        console.log(event);
        if (event.target.value === "") {
          console.log("String Empty");
          return;
        }
      };
    
      return (
        <SpecificationFormContainer>
          <SpecificationFormCard>
            <SpecificationFormTitle>Add Specifications</SpecificationFormTitle>
            <form>
              {[...Array(numberOfSpecFields)].map((e, index) => {
                return (
                  <SpecificationInputRow key={index}>
                    <SpecificationValue
                      placeholder="Key"
                      onChange={handleSpecKeyChange}
                      name="key"
                      onBlur={() => {
                        handleFocusOut(index);
                      }}
                    />
                    <SpecificationValue
                      placeholder="Value"
                      onChange={handleSpecValueChange}
                      name="value"
                      onBlur={() => {
                        handleFocusOut(index);
                      }}
                    />
                  </SpecificationInputRow>
                );
              })}
            </form>
            <AddMoreButton
              onClick={() => {
                setNumberOfSpecFields((prev) => prev   1);
              }}
            >
              Add
            </AddMoreButton>
            {numberOfSpecFields > 0 && (
              <RemoveButton
                onClick={() => {
                  setNumberOfSpecFields((prev) => prev - 1);
                }}
              >
                Remove
              </RemoveButton>
            )}
          </SpecificationFormCard>
        </SpecificationFormContainer>
      );
    }

Elements.js


    import styled from "styled-components";
    
    export const SpecificationFormContainer = styled.div`
      width: 100%;
      border: 2px solid blue;
      padding: 1em;
      display: flex;
      justify-content: center;
      align-items: center;
    `;
    
    export const SpecificationFormCard = styled.div`
      background-color: rgba(0, 0, 0, 0.1);
      box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
      /* min-height: 15em; */
      min-width: 50em;
    `;
    
    export const SpecificationFormTitle = styled.div`
      width: 100%;
      font-size: large;
      text-align: center;
    `;
    
    export const SpecificationInputRow = styled.div`
      width: 100%;
      display: flex;
      justify-content: center;
    `;
    
    export const SpecificationValue = styled.input`
      width: 40%;
      padding: 0.5em;
      margin: 0.5em;
    `;
    
    export const AddMoreButton = styled.button`
      width: 7em;
    `;
    
    export const RemoveButton = styled.button`
      width: 7em;
    `;

In the handleFocusOut function, the event is 0. I was thinking of making an object with the key value pair in the handleFocusOut function based on the index as the key and value input pair have the same index.

I want to know why this does not work and how to make it work. There is most likely a better way to do this as this approach probably is not the best since I am only just a beginner. So, if there is a better way to achieve this, I want to know that.

CodePudding user response:

In the handleFocusOut function, the event is 0.

It's 0 because you are passing index as an argument and ignoring the event. You could use a curried function to accept the event and index as well.

const handleFocusOut = (index) => (event) => {
   // do stuff
};

onBlur={handleFocusOut(index)}

or add a function directly in JSX:

onBlur={(event) => handleFocusOut(event, index)}
  • Related