Home > OS >  How can I use this React component to collect form data?
How can I use this React component to collect form data?

Time:05-19

I've created two components which together create a 'progressive' style input form. The reason I've chosen this method is because the questions could change text or change order and so are being pulled into the component from an array stored in a JS file called QuestionsText

So far I've been trying to add a data handler function which will be triggered when the user clicks on the 'Proceed' button. The function should collect all of the answers from all of the rendered questions and store them in an array called InputData. I've managed to get this to work in a hard coded version of InputForm using the code shown below but I've not found a way to make it dynamic enough to use alongside the Question component. Can anybody help me make the dataHander function collect data dynamically?

dataHander function and variables:

const dateOfBirthInputRef = useRef();
const firstNameInputRef = useRef();
const surnameInputRef = useRef();

function dataHandler() {
  const enteredDateofBirth = dateOfBirthInputRef.current.value;
  const enteredFirstName = firstNameInputRef.current.value;
  const enteredSurname = surnameInputRef.current.value;

  const inputData = {
    dateOfBirth: enteredDateofBirth,
    firstName: enteredFirstName,
    surname: enteredSurname,
  };
  console.log(inputData);
}

InputForm component:

import React, { useState, useRef } from "react";
import { Link, useNavigate } from "react-router-dom";
import Question from "./Question";
import QuestionsText from "../../assets/data/QuestionsText";
import classes from "./InputForm.module.css";

const InputForm = (props) => {
  const [currentIndex, setCurrentIndex] = useState(1);

  const handler = (thisIndex) => {
    if (thisIndex === currentIndex) {
      setCurrentIndex(currentIndex   1);
    }
  };

  const maxIndex = QuestionsText.length;

  const questions = QuestionsText.map((question) => {
    return (
      <Question
        key={question.id}
        ref={question.id}
        thisIndex={question.index}
        currentIndex={currentIndex}
        maxIndex={maxIndex}
        text={question.text}
        type={question.type}
        clickHandler={() => handler(question.index)}
      />
    );
  });

  return (
    <form className={classes.formbox}>
      <div>{questions}</div>
      <div className={classes.btn__container}>
        <button
            className={`${classes.submitbutton} ${
              currentIndex >= maxIndex ? classes.active : classes.inactive
            }`}
        >
          Proceed
        </button>
      </div>
    </form>
  );
};

export default InputForm;

Question component:

import React from "react";
import classes from "./InputForm.module.css";

const Question = (props) => {
  return (
    <section
      className={`${
        props.thisIndex <= props.currentIndex
          ? classes.active
          : classes.inactive
      }`}
    >
      <div className={classes.textbox}>
        <p>{props.text}</p>
        {(() => {
          switch (`${props.type}`) {
            case "date":
              return (
                <input className={classes.input} type="date" required></input>
              );
            case "number":
              return (
                <input
                  className={classes.input}
                  type="number"
                  min="1"
                  step="any"
                  required
                />
              );
          }
        })()}
      </div>
      <div className={classes.btn_container}>
        <button
          type="button"
          className={`${classes.button} ${
            props.thisIndex < props.currentIndex ? classes.disabled : ""
          }
           ${props.thisIndex === props.maxIndex ? classes.inactive : ""}`}
          onClick={props.clickHandler}
        >
          Next
        </button>
      </div>
    </section>
  );
};

export default Question;

CodePudding user response:

There what I have done:

https://codesandbox.io/s/angry-dew-37szi2?file=/src/InputForm.js:262-271

So, we can make it easier, you just can pass necessary data when call handler from props:

  const inputRef = React.useRef();

  const handleNext = () => {
    props.clickHandler(props.reference, inputRef.current.value);
  };

And merge it at InputForm component:

  const [inputData, setInputData] = useState({});

  const handler = (thisIndex) => (key, value) => {
    if (thisIndex === currentIndex) {
      setCurrentIndex(currentIndex   1);
      setInputData((prev) => ({
        ...prev,
        [key]: value
      }));
    }
  };

  // ...
    <Question
        // ...
        clickHandler={handler(question.index)}
      />

So, you wanted array (object more coninient I think), you can just save data like array if you want:

setInputData(prev => [...prev, value])

Initially, I thought you want to collect data on button clicks in the InputForm, but apparently you can do without this, this solution is simpler

  • Related