React hook useState. Каким образом можно навесить хук на неизвестное количество элементов, при использовании map

Создаю приложение в котором получаю данные с базы, количество данных заранее неизвестно. Необходимо каким то образом навесить на каждый элемент списка хук useState для дальнейшей работы с каждым элементом (по отдельности). Пример кода.

const [BtnNameUser, setBtnNameUser] = useState();
const List_vm = ({vm_list}) => {
    const listItems = vm_list.map(vm => {
        return(
            <div>
                <p>{Object.keys(vm)[0]}</p>
                <input type="button" value={BtnNameUser} onClick={() => btn_click(Object.keys(vm)[0])}/>
            </div>
        );
    });
    return (<div>{listItems}</div>);
}

Если я делаю таким образом, значение ставиться для всех элементов одно и тоже. Буду благодарен любой помощи.


Ответы (2 шт):

Автор решения: Konstantin Modin

При использовании map необходимо возвращать компонент, а внутри этого компонента можно создать любое количество хуков. Примерно так:

// import React from "react";

const data = [
  { id: 1, title: "Title1", userName: "User1" },
  { id: 2, title: "Title2", userName: "User2" },
  { id: 3, title: "Title3", userName: "User3" },
  { id: 4, title: "Title4", userName: "User4" },
];

const App = () => {
  return (
    <div>
      <ListVm vm_list={data} />
    </div>
  );
};

// export default App;

const ListVm = ({ vm_list }) => {
  return (
    <div>
      {vm_list.map((item) => (
        <ItemComponent item={item} key={item.id} />
      ))}
    </div>
  );
};

const ItemComponent = ({ item }) => {
  const [btnNameUser, setBtnNameUser] = React.useState(item.userName);

  return (
    <div>
      <p>{item.title}</p>
      <input
        type="input"
        value={btnNameUser}
        onChange={({ target: { value } }) => setBtnNameUser(value)}
      />
    </div>
  );
};




ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

→ Ссылка
Автор решения: Dmitry

Создать отдельный компонент для каждого шага. Сразу скажу не уверен хороший ли это подход, но он работает
Компонент с div

export function DivElement(props) {
  const [btnUser, setBtnUser] = useState(props.btnUser)
  return (
    <div>
      <p>{props.keysVM}</p>
      <input
        type="button"
        value={btnUser}
        onClick={() => btn_click(props.keysVM)}
      />
    </div>
  );
}

И пробежаться map

import {DivElement} from ---blablabla----

const listItems = vm_list.map((vm) => {
  return <DivElement btnUser={BtnNameUser} keysVM={Object.keys(vm)[0]} />;
});

Примерно так, код не тестировал, но идея должна быть ясна

→ Ссылка