Pass answers from child component to parent component to add to cart

Viewed 35

I've spent a few days going back and forth now trying to figure this one out but I'm unable to.

First off it's easiest to describe the end goal.

  1. In SectionQuestions component there is an add to cart button, on click it should send an object of data to the cartItems state.
  2. The SectionQuestions component gets its data from the QuestionsList component.
  3. The QuestionsList component gets it's answers from the 2 different input components

The issues I am facing:

  1. The questions are dynamically pulled from WordPress so the code must be dynamic as questions cant be hardcoded.
  2. There are multiple questions depending on what service is selected.
  3. When using a radio button the value was added to an object twice instead of overwriting the previous value.
  4. I am using ChakraUI where I don't believe you can expand on their onChange value for RadioGroups so I am unable to run code as a handler instead must use the useEffect hook

What I Think the solution is

I believe that each input should pass its answer up to the parent component. I believe the QuestionsList component should store the answer and know where the answer came from. (This is less of a challenge for the text/number field and more so an issue for radio buttons)

Let's get into some code... I apologise in advance there's a lot for the purpose of length I will display only the required sections of each file:

SectionQuestions.js

allWpService.nodes.map(service => {
    return (
    <div key={service.id}>
        {selected === service.id ? (
        <div>
            <p>{service.title}</p>
            <QuestionList service={service} />
        </div>
        ) : null}
    </div>
    )
})

QuestionList.js

import React, { useState } from "react"
import InputRadioButton from "../InputFields/InputRadioButton"
import InputTextNumber from "../InputFields/InputTextNumber"

const QuestionList = ({ service }) => {
const [answers, setAnswers] = useState([])

const setAnswersValue = index => {
    setAnswers(answers.push(index))
    console.log(answers)
}

return (
    <>
    {service.serviceQuestions.questions.map(questions => {
        return (
        <div key={questions.questionTitle}>
            <p>{questions.questionTitle}</p>
            {questions.questionInputField.map(fields => {
            if (
                fields.inputType === "number" ||
                fields.inputType === "text"
            ) {
                return (
                <InputTextNumber
                    fieldData={fields}
                    setAnswersValue={setAnswersValue}
                />
                )
            } else if (fields.inputType === "radio") {
                return (
                <InputRadioButton
                    fieldData={fields}
                    columns={questions.enableColumnLayout}
                    setAnswersValue={setAnswersValue}
                />
                )
            } else {
                return <p>Failed to get Input Type</p>
            }
            })}
        </div>
        )
    })}
    </>
)
}

export default QuestionList

InputTextNumber.js

//This Input field is a number field
import React from "react"
import {
  NumberInput,
  NumberInputField,
  NumberInputStepper,
  NumberIncrementStepper,
  NumberDecrementStepper,
} from "@chakra-ui/react"
import { useState } from "react"

const InputTextNumber = ({ fieldData, questionsAnswers }) => {
  const [value, setValue] = useState(0)

  return (
    <NumberInput
      size="lg"
      defaultValue={0}
      onChange={valueString => {
        setValue(valueString)
        questionsAnswers(valueString)
      }}
      value={value}
    >
      <NumberInputField />
      {fieldData.inputType === "number" ? (
        <NumberInputStepper>
          <NumberIncrementStepper />
          <NumberDecrementStepper />
        </NumberInputStepper>
      ) : null}
    </NumberInput>
  )
}

export default InputTextNumber

InputRadioButton.js

import React, { useEffect } from "react"
import "../../css/InputRadioButton.css"
import { Radio, RadioGroup } from "@chakra-ui/react"

const InputRadioButton = props => {
  const [value, setValue] = React.useState("")
  const radios = props.fieldData.radioButtons
  const questionId = "12342341"

  function setValueProps(id, value) {
    const obj = {}
    obj[id] = { value: value }
    props.setAnswersValue(obj)
  }

  useEffect(() => {
    setValueProps(questionId, value)
  }, [value])

  return (
    <RadioGroup onChange={setValue} value={value}>
      <div
        className={
          props.fieldData.columns === true ? "flex-row" : "flex-column"
        }
      >
        {radios.map(radio => {
          return (
            <div
              className={`radio-container ${
                value === radio.inputLabel ? "active" : ""
              }`}
              key={radio.inputLabel}
            >
              <div className="radio-wrapper" id={radio.inputImagePosition}>
                {radio.inputImage && radio.inputImagePosition !== "no-image" ? (
                  <div className="image-wrapper">
                    <img
                      src={radio.inputImage.sourceUrl}
                      alt={radio.inputLabel}
                    />
                  </div>
                ) : null}

                {radio.inputImagePosition === "no-image" ? (
                  <div className="radio-button-wrapper">
                    <Radio
                      value={radio.inputLabel}
                      name={radio.inputLabel}
                      size="lg"
                      colorScheme="green"
                    />
                  </div>
                ) : null}

                <div className="radio-content">
                  {radio.inputImagePosition === "image-top" ? (
                    <div className="radio-button-wrapper">
                      <Radio
                        value={radio.inputLabel}
                        name={radio.inputLabel}
                        size="lg"
                        colorScheme="green"
                      />
                    </div>
                  ) : null}
                  {radio.inputIntroPosition === "above" &&
                  radio.inputIntro !== "none" &&
                  radio.inputIntro !== null ? (
                    <div className="radio-content-wrapper">
                      <p className="radio-intro">{radio.inputIntro}</p>
                      <p className="radio-label">{radio.inputLabel}</p>
                      <p className="radio-description">
                        {radio.inputDescription}
                      </p>
                    </div>
                  ) : radio.inputIntroPosition === "below" &&
                    radio.inputIntro !== "none" &&
                    radio.inputIntro !== null ? (
                    <div className="radio-content-wrapper">
                      <p className="radio-label">{radio.inputLabel}</p>
                      <p className="radio-intro">{radio.inputIntro}</p>
                      <p className="radio-description">
                        {radio.inputDescription}
                      </p>
                    </div>
                  ) : (
                    <div className="radio-content-wrapper">
                      <p className="radio-label">{radio.inputLabel}</p>
                      <p className="radio-description">
                        {radio.inputDescription}
                      </p>
                    </div>
                  )}
                </div>

                {radio.inputImagePosition === "image-left" ? (
                  <div className="radio-button-wrapper">
                    <Radio value={radio.inputLabel} name={radio.inputLabel} />
                  </div>
                ) : null}
              </div>
            </div>
          )
        })}
      </div>
    </RadioGroup>
  )
}

export default InputRadioButton
0 Answers
Related