Pedro Vieira
Pedro Vieira

Reputation: 2316

How to use map function for hooks useState properties dynamically

My question is almost the same as this one.

In this case, the person has a map of states created in a hard coded way:

const App = props => {
  const [state, changeState] = useState({
    name: "",
    eventTitle: "",
    details: "",
    list: "",
    toggleIndex: "",
    editName: "",
    editEventTitle: "",
    editDetails: "",
  });

The difference is that I want to create those states dynamically, receiving them from another component. I tried something like this but it obviously did not work:

const App = props => {
  const [state, changeState] = useState({
    props.inputs.map((input, i) =>
      input = ""
    )
  });

Do you know any solution for this?

Upvotes: 3

Views: 8585

Answers (3)

PHANTOM-X
PHANTOM-X

Reputation: 586

in my case I was trying to get an item unique ID when click on mapped items, and opening a dialog to confirm selected item to be deleted, as shown below

export const StatsTable = (props) => {
  const [itemUid, setItemUid] = useState('')
  const [open, setOpen] = useState(false)

  const handleClickOpen = () => {
    setOpen(true)
  }

  console.log('====================================')
  console.log(itemUid)
  console.log('====================================')
...
 return (
...
  {items.map((item) => {
...
    <Button
      type="submit"
      onClick={() =>
        handleClickOpen(setItemUid(item.uid))
      }
     >
       Delete
     </Button>
   }
}

...

Image Example

Upvotes: 0

Christos Lytras
Christos Lytras

Reputation: 37298

You can do this by using the props.inputs directly to the state combine it with reduce to create a new object from the inputs array:

const App = props => {
  const [state, changeState] = useState(
    props.inputs.reduce((acc, cur, arr) => ({
      [cur]: "",
      ...acc
    }), {})
  );

  return (
    <ul>
      {Object.entries(state).map(([name, value], index) => (
        <li key={`li-${index}`}><strong>{name}</strong>: {`"${value}"`}</li>
      ))}
    </ul>
  );
}

If we use it like this:

<App inputs={['name', 'details', 'list', 'editName']}/>

We'll have a result like this:

editName: ""
list: ""
details: ""
name: ""

You can check the working Stackblitz here.

Upvotes: 2

bilwit
bilwit

Reputation: 819

Assuming props.input is just an array of the keys you want, you can populate the state object by iterating through the array and dynamically assigning the state object key with []

const [state, changeState] = useState({});

useEffect(() => {
    props.input.forEach(item => changeState(prevState => ({...prevState, [item]: "" })));
}, [props.input])

Upvotes: 3

Related Questions