0

I try to map an objects properties names and values to produce input fragments. While the mapping works for the initial input values it doesnt work to iterate through the properties names to call their state hooks.

I tried many approaches like; Object.entries(hurdleRates).map(([key, value]) => {... })` OR Object.keys(hurdleRates).map(function(key) {... })`

Please Help! Thanks!

import React, { useState } from "react";

const RateSettings = () => {

const [hurdleRates, sethurdleRates] = useState({
    bcLombard: 0.1,
    bcOtherSecured: 0.2,
    bcUnsecured: 0.3
  });

  return (
    <div>
      {Object.keys(hurdleRates).map(function(key) {
        return (
          <input
            value={hurdleRates[key]}
            onChange={e => sethurdleRates({ key: e.target.value })}
          ></input>
        );
      })}
    </div>
  );
};

export default RateSettings;

As an Outcome I expect three input tags generating three input boxes. In the code each should look like the following first one;

<input value=0.1 onChange{e => sethurdleRates({bcLombard : e.target.value})}> </input>
mafehx
  • 363
  • 2
  • 6
  • 14

2 Answers2

1

Use Object.entries(), but use the key as the property of the state you want to assign to using computed property names { ...state, [key]: e.target.value }.

Note: you should also spread the state if you don't want to use the other inputs - { ...state, [key]: e.target.value }.

const { useState } = React;

const RateSettings = () => {
  const [hurdleRates, sethurdleRates] = useState({
    bcLombard: 0.1,
    bcOtherSecured: 0.2,
    bcUnsecured: 0.3
  });

  return (
    <div>
      {Object.entries(hurdleRates).map(([key, value]) => {
        return (
          <input
            key={key}
            value={value}
            type="number"
            onChange={e => sethurdleRates({ ...hurdleRates, [key]: +e.target.value })}
          ></input>
        );
      })}
    </div>
  );
};

ReactDOM.render(
  <RateSettings />,
  root
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
0

You're missing just a couple of things:

Your are passing key for the key, which is the literal value Object.key. What you want is [key] aka Object[key]. With object literal syntax that looks like

onChange={e => sethurdleRates({ [key]: e.target.value })}

But if that's all you had you would be blowing out all the values of your other keys. You need to preserve the other key value pairs in your state object:

onChange={e => sethurdleRates(rates => ({
  ...rates,
  [key]: e.target.value 
}))}
azium
  • 20,056
  • 7
  • 57
  • 79