Serdar Mustafa
Serdar Mustafa

Reputation: 925

map through inputs and setstate onchange

I am trying to return several text inputs based on the data in the state below (placementData) and then handle updating their respective state using a single onChange handler.

I can comfortably .map and return the inputs and their placeholders, values etc but I am stuck with how to carry out the onChange.

I really don't want to update each one separately/

  const [placementData, setPlacementData] = useState([
    { key: 1, position: 'Long side panel', value: 10 },
    { key: 2, position: 'Custom wrap', value: 0 },
    { key: 3, position: 'Seatback', value: 0 },
    { key: 4, position: 'Full wrap', value: 20 },
    { key: 5, position: 'Driver’s cabin', value: 0 },
    { key: 6, position: 'Stop side panel', value: 0 },
    { key: 7, position: 'Max Parade', value: 60 },
    { key: 8, position: 'Parade', value: 0 },
    { key: 9, position: 'Full rear', value: 70 },
    { key: 10, position: 'Rear panel', value: 0 },
  ]);

This is my current broken solution:

  const handleInputChange = (e, index) => {
    const { name, value } = e.target;
    const list = [...placementData];
    list[index][name] = value;
    setPlacementData(list);
  };

return (
  <div>
              <h4>Add Campaign Placements</h4>
              <Row>
                {placementData.map((key, i) => (
                  <Col xs={6} md={6} lg={3} key={key.position}>
                    <TextField
                      label={key.position}
                      name={key.position}
                      value={key.value}
                      // defaultValue={selected[0].company}
                      variant="outlined"
                      // onChange={handleInputChange}
                      onChange={(e) => handleInputChange(e, key, i)}
                      InputProps={
                        {
                          // readOnly: isReadOnly,
                        }
                      }
                    />
                  </Col>
                ))}
              </Row>
            </div>

I also tried:

  // const handleInputChange = (event) => {
  //   const { value } = event.target;
  //   setPlacementData({
  //     ...placementData,
  //     [event.target.name]: value,
  //   });
  // };

and


  const handleInputChange = (event, idx) => {
    setPlacementData(() => placementData.map((item, i) => i.value));
  };

Does anyone know how I can actually complete this?

Upvotes: 0

Views: 1195

Answers (1)

Yatrix
Yatrix

Reputation: 13775

handleInputChange(e, key, i) is how you're calling your handler, but the signature of your handler is (e, index). So, you're passing the key in where you're supposed to be passing in the index.

Update your handler to this and I think you should be good to go.

 const handleInputChange = (e, index) => {
    const { name, value } = e.target;
    const list = [...placementData];

    // it's an array element, not a keyed map/object, 
    // so have to recreate the entire element
    list[index] = { ...list[index], value };
    setPlacementData(list);
  };

Upvotes: 2

Related Questions