简体   繁体   中英

React: How to build dynamic input fields that display user data from database

I have dynamic input fields that come from my database. generating the input fields aren't a problem. however once the user enters the information, they may want to come back and change the input. I am having trouble with the edit component. It seems that if I put anything in the value property, the text in the field will not change. For clarity, lets say I have 5 inputs but the user only fills in 2. I want their data to display in the right inputs. Here is what I am doing.

  useEffect(() => {
    fetchPlatformInputs();
  }, []);

const fetchPlatformInputs = async () => {

  const fetchInputs = async () => {
    const fetchedInputs = await API.graphql({
      query: sortInputsByType,
      variables: { type: "*", sortDirection: "ASC" },
    });

  const { items } = fetchedInputs.data.sortInputsByType;  <--- the input fields

// Then the user's input for each field is held in context (which is derived from the user table) so I loop over both object arrays to create one object array of dynamic inputs with user data.

contextUser.inputData.map((contextData) => {
      for(const item of items) {
        if (contextData.inputType === item.inputType) {
         item.inputData = contextData.inputData;
        }
      }
    });

// Now I have an object array that joined the dynamic inputs and user data and I set put that into state.  

setPlatformInputs(items);

};

/// that is just a useState combo.  I loop over this variable to create the dynamic inputs.

  const [platformInputs, setPlatformInputs] = useState([]);

//. Okay now for the part I can't figure out.

// here is where I hold the form data:

const [formValues, setFormValues] = useState([]);

// the onchange handler builds an object array for database insertion.

  let handleChange = (e, inputType, inputData, isFabIcon, iconColor, imagePath) => {
    
    setFormValues({
      ...formValues,
      [inputType]: {
        inputType: inputType,
        inputData: inputData,
        isFabIcon: isFabIcon,
        iconColor: iconColor,
        imagePath: imagePath,
      },
    });


    console.log("form values are ", formValues);
  };

//. here are the dynamic fields

 {platformInputs?.length > 0 &&
          platformInputs.map((input, index) => (
            <MDBRow
              className="mx-auto my-2 text-center"
              key={"r" + index + "_" + input.inputType}
            >
              <MDBCol sm="2" key={"c1_" + input.inputType}>
                // image or icon goes here
              </MDBCol>
              <MDBCol sm="10" key={"c2_" + input.inputType}>
                <MDBInput
                  name={["input_" + input.inputType]}
                  label={[capitalizeWords(input.inputType)]}
                  type="text"
                  value={input.inputData}.  <-- here is the problem.  I can't figure out how to display the initial incoming user data and update it with the state formValues variable derived from the onChange handler
                  onChange={(e) =>
                    handleChange(
                      e,
                      input.inputType,
                      input.inputData,
                      input.isFabIcon,
                      input.iconColor,
                      input.imagePath
                    )
                  }
                />
              </MDBCol>
            </MDBRow>
          ))}




So this collects the data and displays it perfectly. The only problem is that state is not working so the user cannot edit the field. The input value remains the same no matter what the user types.

Please not that the user does not have to input data into every input field. so the formValues variable only holds those they use. Otherwise I would probably just loop over the formValues array. ' Thank you for your help.

Basic example

import React, { useState, useEffect } from 'react';

const DynamicInputFields = () => {
  const [userData, setUserData] = useState([]);
  const [inputFields, setInputFields] = useState([]);

  useEffect(() => {
    // fetch user data from database
    const fetchUserData = async () => {
      const response = await fetch('your-api-endpoint');
      const data = await response.json();
      setUserData(data);
    };
    fetchUserData();
  }, []);

  useEffect(() => {
    setInputFields(userData.map((item, index) => (
      <div key={index}>
        <input
          type="text"
          value={item.value}
          onChange={(e) => handleInputChange(e, index)}
        />
      </div>
    )));
  }, [userData]);

  const handleInputChange = (e, index) => {
    const updatedData = [...userData];
    updatedData[index].value = e.target.value;
    setUserData(updatedData);
  };

  return (
    <form>
      {inputFields}
      <button type="submit">Submit</button>
    </form>
  );
};

export default DynamicInputFields;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM