Search code examples
reactjsstateapollo-clientgql

How to useState on a set of mapped <input> elements


I built a day planner that allows users to add days to a travel plan and add activities to a day. I have created Apollo client mutations and queries so users can add days by clicking a button and clicking another button to query all the days added into the database.

Right now I have a problem using states on these mapped days since I cannot use for loops to set states for these mapped "days" and I can't find a solution anywhere. How should I solve this problem? (Currently, the mapped elements of the same time share the same state and I cannot update a specific day individually)

The mapped days that the user decides to create and input for the different times:

return (
        <div className="container">
            <button onClick={handleAddDay}>Add Day</button>
            <button onClick={handleFetch}>Check Day</button>
            <div>
            {planData ? planData.singlePlan.days.map((days) => {
                return (
                    <div className="text-left">
                        <h2>Day {days.dayNumber + 1} </h2>
                        <form>
                            <label>9am: </label>
                            <input type="text" onChange={handleChange1} value={dayInfo1}></input>
                            <br></br>
                            <label>12am: </label>
                            <input type="text" onChange={handleChange2} value={dayInfo2}></input>
                            <br></br>
                            <label>3pm: </label>
                            <input type="text" onChange={handleChange3} value={dayInfo3}></input>
                            <br></br>
                            <label>6pm: </label>
                            <input type="text" onChange={handleChange4} value={dayInfo4}></input>
                        </form>
                    </div>
                )
            }) : ('No Data yet')
            }
            </div>
            <button>Rock and Roll!</button>
            <h1>Number of days: {day}</h1>
            
        </div>
    )

The use states are defined here:

    //text from 9am
    const [dayInfo1, setdayInfo1] = useState();
    const handleChange1 = (event) => {
        setdayInfo1(event.target.value);
    };
    //text from 1pm
    const [dayInfo2, setdayInfo2] = useState();
    const handleChange2 = (event) => {
        setdayInfo2(event.target.value);
    };
    //text from 3pm
    const [dayInfo3, setdayInfo3] = useState();
    const handleChange3 = (event) => {
        setdayInfo3(event.target.value);
    };
    //text from 5pm
    const [dayInfo4, setdayInfo4] = useState();
    const handleChange4 = (event) => {
        setdayInfo4(event.target.value);
    };

The form at the front end after I created 5 days.


Solution

  • I think tou need to do your form as component with this useStates. And I recommend you to use object in state, then you only need one function to manage your form.

    const [dayInfo, setdayInfo] = useState({
        9: '',
        12: '',
        3: '',
        6: '',
    });
    
    const handleChange = (event, fieldToUpdate) => {
        setdayInfo(prevState => {
            ...prevState,
            [fieldToUpdate]: event.target.value
        });
    };