chrus54321
chrus54321

Reputation: 125

Dynamically creating and getting inputs

I need to dynamically add new input fields on button click as well as get the user input of those inputs in an array. This is what I have and Im not sure how to do the array. Also on the screen the components only update when I change the state. Not on button click. This is what I have:

import React, { useState } from 'react'

const CreatePoll = () => {


const [formData, setFormData] = useState({
    question: '',
    options: ['hi', 'there']
});

const {
    question,
    options
} = formData;

const addOption = e => {
    e.preventDefault();

    options.push([''])

    console.log(options.length);
}

const handleQuestionChange = (e) => setFormData({
    ...formData,
    [e.target.name]: e.target.value
})

const handleOptionChange = e => setFormData({
    ...formData
    // options: []
})


const handleSubmit = async e => {
    e.preventDefault();

    console.log(formData)
}

return (
    <form onSubmit={handleSubmit}>
        <input 
            placeholder="enter your question" 
            type="text" 
            onChange={handleQuestionChange}
            name="question" />
        {options.map(() => {
            return (
                <input 
                    placeholder="option" 
                    type="text" 
                    onChange={handleOptionChange}
                    name="option" />
            )
        })}
        <input type="button" value="Add new option" onClick={addOption} />
        <input type="submit" value="Submit" />
    </form>
)
}

export default CreatePoll

I tried when addOption button is clicked, I add to the options state an empty string. The length of the array updates but the components on the screen dont until I type in the input box and the state changes. Also I need to map the values of the input boxes to their respective place in the array. They should also be able to edit at any time. How is this done?

Upvotes: 0

Views: 80

Answers (2)

Pierre
Pierre

Reputation: 51

Several things are wrong here :

  1. You don't set your state in addOption, don't modify direcly the state object, prefere to destructure array, modify it and set the state.
  2. Your map function don't take any parameter, so it will be the same input names every time, use parameter and index to now which option to change in handleQuestionChange
  3. Your addOption could be improved by using question property directly in you setFormData (it worked like you did it, but it seems to me more clean with this)

    import React, { useState } from 'react';
    
    const CreatePoll = () => {
      const [formData, setFormData] = useState({
        question: '',
        options: ['hi', 'there'],
      });
    
      const {
        question,
        options,
      } = formData;
    
      const addOption = e => {
        e.preventDefault();
        const newOptions = [...options];
        newOptions.push('');
    
        setFormData({ ...formData, options: newOptions });
        console.log(options.length);
      };
    
      const handleQuestionChange = e => {
        setFormData({
          ...formData,
          question: e.target.value,
        });
      };
    
    const handleOptionChange = (e, index) => {
      const newOptions = [...options];
      newOptions[index] = e.target.value;
    
      setFormData({
        ...formData,
        options: newOptions,
      });
    };
    
    
    const handleSubmit = async e => {
      e.preventDefault();
    
      console.log(formData);
    };
    
    return (
      <form onSubmit={handleSubmit}>
        <input
          placeholder="enter your question"
          type="text"
          onChange={handleQuestionChange}
          name="question"
        />
        {options.map((opt, index) => (
          <input
            value={opt}
            key={`option_${index}`}
            placeholder="option"
            type="text"
            onChange={e => handleOptionChange(e, index)}
            name={opt}
          />
        ))}
        <input type="button" value="Add new option" onClick={addOption} />
        <input type="submit" value="Submit" />
      </form>
     );
    };
    
    export default CreatePoll;
    

Upvotes: 1

Red Baron
Red Baron

Reputation: 7642

to add new options on button click you need to change this function:

const addOption = e => {
    e.preventDefault();
    options.push([''])
    console.log(options.length);
}

to be

const addOption = e => {
    e.preventDefault();
    const newOptions = {...formData.options}
    newOptions.concat([''])
    setFormData({...formatData, options: newOptions)}
}

Upvotes: 0

Related Questions