Home > Software design >  Apply JSON groups to TextFields or Selects based on a JSON Value
Apply JSON groups to TextFields or Selects based on a JSON Value

Time:04-08

I have a bunch of JSON groups pulled from an API. Each group contains 1 or more questions objects. I need to append each question to a textField with its corresponding response in either a MUI TextField or Select, which needs to be decided based on the QuestionType value.

Below is how I am trying to get data to display to a TextField. The TextFields are being populated with [object Object] as they are now.

const [questions, setQuestions] = useState("");

const fetchQuestions = async () => {
   setQuestions(
      await fetch(`/fiscalyears/FY2023/intakes/${params.id}/details/questions`)
            .then((response) => response.json())
   );
};

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

...

{questions["question_groups"]?.map((row) => (
   <TextField
      fullWidth
      multiline
      className="text-field"
      value={row?.questions || ""}
      variant="outlined"
      margin="normal"
      label={row["GroupName"]}
   />
))}

Here is an example of my JSON. In reality, there could be 20 groups within question_groups

{
   "question_groups": [
      {
         "GroupName": "DDD",
         "questions": [
            {
               "Question": "1. Do you need a drink?",
               "QuestionType": "Select",
               "Response": null,
               "Choices": [
                  "Yes",
                  "No"
               ]
            }
         ]
      },
      {
         "GroupName": "FED",
         "questions": [
            {
               "Question": "2. What do you want to drink?",
               "QuestionType": "Text",
               "Response": null,
               "Choices": [
               ]
            },
            {
              "Question": "3. Do you want something to eat?",
               "QuestionType": "Text",
               "Response": "I would like steak",
               "Choices": [
               ] 
            }
         ]
      }
   ],
}

Any help or advice would be greatly appreciated.

CodePudding user response:

First, it doesn't make sense to initialise questions as a String. Try an object.

const [questions, setQuestions] = useState({});

Also, it's not clear that you are actually assigning the results of fetchQuestions to questions; Assuming you get all the questions you need from a single call, I'll assume you do this with setQuestions(response.json()) or similar.

If you are in control of the JSON structure, I would change it, but assuming you can't, then, how I would map these to alternate between Select and TextField would be something like this:

const App = () => {
    //... assume you have a state called `questions`
    //populated with your JSON object
    
    //create a component for each type
    const TextQuestion = ({question}) => {
        return(
            <div>
                <TextField //with your question and any necessary props
                />
                <TextField //with your answer
                />
            </div>
        )
    }
    
    const SelectQuestion = ({question}) => {
        return (
            <div>
                <TextField //with your question text
                />
                <Select //with your answer options
                />
            </div>
        )
    }

    //map the array of question_groups, then map the array 
    //of questions in each group and return one of your
    //component types depending on the value of QuestionType

    const questionComps = questions["question_groups"].map((group, i) => {
        return group["questions"].map((question, i) => {
            return question["QuestionType"] === "Text" 
            ? <TextQuestion key={`${i}${question.Question}`} question={question}/>
            : <SelectQuestion key={`${i}${question.Question}`} question={question} />
        })
    })
    //render the collection of question components
    return (
        <div>{questionComps}</div>
    )
}
  • Related