Как внутри REACT компонента сделать цикл, если используется useState?
Изначально отправляю массив объектов чтобы вывести список чекбоксов.
<Checkbox checkboxProps = {checkboxButtonsDataArr}/>
Нужно чтобы на выходе внутри <form></form> было 3 <label></label>
Массив с пропсами:
[
{id: 1, title: 'Тест 1', name: 'name1', checked: false},
{id: 2, title: 'Тест 2', name: 'name2', checked: false},
{id: 3, title: 'Тест 3', name: 'name3', checked: true}
]
Компонент:
interface IChecked {
id: number;
title: string;
name: string;
checked: boolean;
}
interface ICheckedArr {
checkboxProps: IChecked[];
}
const Checkbox = ({ checkboxProps }: ICheckedArr) => {
console.log(checkboxProps);
const [checked, setChecked] = useState(false);
return (
<div>
<form>
{checkboxProps.map((item) => {
return (
<label key={item.id}>
<input
type="checkbox"
name={item.name}
checked={checked}
onChange={(e) => setChecked(e.target.checked)}
/>
<span>{item.title}</span>
</label>
);
})}
</form>
</div>
);
};
export default Checkbox;
Я пытался сделать общий useState, но создать useState для проверки на checked внутри цикла нельзя.
upd. Добавил мою попытку, но опять таки это ссылается на один и тот же setChecked и по клику они все checked
upd2. это не дубликат, в предложенном варианте нет setState в цикле
Ответы (1 шт):
Могу предложить вариант — делается компонент Checkbox для одного элемента, там же стейт для checked, таким образом каждый чекбокс хранит свое состояние. Изменение этого состояния не будет приводить к перерисовке всего списка. Но пользы в этом мало если мы не можем получить все данные в одном месте, именно в списке чекбоксов CheckboxList мы и будем хранить данные. Для передачи состояния от компонента Checkbox в данные CheckboxList используется функция update — так как она обновляет вложенные данные стейта, перерисовка списка происходить не будет.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Add React in One Minute</title>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin ></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin ></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
<!-- Load our React component. -->
<script type="text/babel">
window.useState = React.useState;
window.useEffect = React.useEffect
const data = [
{id: 1, title: 'Тест 1', name: 'name1', checked: false},
{id: 2, title: 'Тест 2', name: 'name2', checked: false},
{id: 3, title: 'Тест 3', name: 'name3', checked: true}
]
const Checkbox = ({ id, title, name, checked:ch, update={update} }) => {
const [checked, setChecked] = useState(ch);
const onChange = (e) => {
setChecked(e.target.checked)
update(id, e.target.checked)
}
return (
<div>
<label key={id}>
<input
type="checkbox"
name={name}
checked={checked}
onChange={onChange}
/>
<span>{title}</span>
</label>
</div>
);
};
const CheckboxList = ({data:dt}) => {
const [data, setData] = useState(dt);
const update = (id, checked) => {
data.find(e => e.id === id).checked = checked
console.log(data.map(e => e.checked).toString())
}
return (
<div>
<form>
{data.map(({id, title, name, checked}) => {
return (
<Checkbox
key={id}
id={id}
type="checkbox"
title={title}
name={name}
checked={checked}
update={update}
/>
);
})}
</form>
</div>
);
};
const App = () => {
return (
<div>
<CheckboxList data={data}/>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
</script>
</body>
</html>