javascript 如何使用反应钩子实现多个复选框
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/56273038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement multiple checkbox using react hook
提问by Nakesh
I want to implement multiple checkboxes on my HTML page using react-hook.
我想使用 react-hook 在我的 HTML 页面上实现多个复选框。
I tried implementing using this URL: https://medium.com/@Zh0uzi/my-concerns-with-react-hooks-6afda0acc672. In the provided link it is done using class component and working perfectly but whenever I am using React hook setCheckedItems to update checkbox checked status it's not re-rendering the view.
我尝试使用这个 URL 实现:https: //medium.com/@Zh0uzi/my-concerns-with-react-hooks-6afda0acc672。在提供的链接中,它是使用类组件完成的并且运行良好,但是每当我使用 React hook setCheckedItems 更新复选框选中状态时,它都不会重新渲染视图。
The very first time the view is rendering and console.log() is printing from Checkbox component. After clicking on checkbox function handleChangegets called and checkedItemsupdates the value but the view is not rendering again (no console.log() printing). And {checkedItems.get("check-box-1")}is also not printing any value.
第一次渲染视图并且 console.log() 从 Checkbox 组件打印。单击复选框函数handleChange被调用后,checkedItems更新值但视图不再呈现(没有 console.log() 打印)。而{checkedItems.get("check-box-1")}也没有打印任何值。
Below is my sample code.
下面是我的示例代码。
CheckboxExample:
复选框示例:
import React, { useState } from 'react';
import Checkbox from '../helper/Checkbox';
const CheckboxExample = () => {
const [checkedItems, setCheckedItems] = useState(new Map());
const handleChange = (event) => {
setCheckedItems(checkedItems => checkedItems.set(event.target.name, event.target.checked));
console.log("checkedItems: ", checkedItems);
}
const checkboxes = [
{
name: 'check-box-1',
key: 'checkBox1',
label: 'Check Box 1',
},
{
name: 'check-box-2',
key: 'checkBox2',
label: 'Check Box 2',
}
];
return (
<div>
<lable>Checked item name : {checkedItems.get("check-box-1")} </lable> <br/>
{
checkboxes.map(item => (
<label key={item.key}>
{item.name}
<Checkbox name={item.name} checked={checkedItems.get(item.name)} onChange={handleChange} />
</label>
))
}
</div>
);
}
export default Example;
Checkbox:
复选框:
import React from 'react';
const Checkbox = ({ type = 'checkbox', name, checked = false, onChange }) => {
console.log("Checkbox: ", name, checked);
return (<input type={type} name={name} checked={checked} onChange={onChange} /> )
}
export default Checkbox;
回答by pawel
I don't think using a Mapto represent the state is the best idea.
I have implemented your example using a plain Objectand it works:
我不认为使用 aMap来代表状态是最好的主意。
我已经使用一个普通的例子实现了你的例子Object,它可以工作:
https://codesandbox.io/s/react-hooks-usestate-xzvq5
https://codesandbox.io/s/react-hooks-usestate-xzvq5
const CheckboxExample = () => {
const [checkedItems, setCheckedItems] = useState({}); //plain object as state
const handleChange = (event) => {
// updating an object instead of a Map
setCheckedItems({...checkedItems, [event.target.name] : event.target.checked });
console.log("checkedItems: ", checkedItems);
}
const checkboxes = [
{
name: 'check-box-1',
key: 'checkBox1',
label: 'Check Box 1',
},
{
name: 'check-box-2',
key: 'checkBox2',
label: 'Check Box 2',
}
];
return (
<div>
<lable>Checked item name : {checkedItems["check-box-1"]} </lable> <br/>
{
checkboxes.map(item => (
<label key={item.key}>
{item.name}
<Checkbox name={item.name} checked={checkedItems[item.name]} onChange={handleChange} />
</label>
))
}
</div>
);
}
EDIT:
编辑:
Turns out a Mapcan work as the state value, but to trigger a re-render you need to replace the Map with a new one instead of simply mutating it, which is not picked by React, i.e.:
结果证明 aMap可以用作状态值,但要触发重新渲染,您需要用新的 Map 替换 Map 而不是简单地改变它,React 不会选择它,即:
const handleChange = (event) => {
// mutate the current Map
checkedItems.set(event.target.name, event.target.checked)
// update the state by creating a new Map
setCheckedItems(new Map(checkedItems) );
console.log("checkedItems: ", checkedItems);
}
but in this case I think there is no benefit to using a Map other than maybe cleaner syntax with .get()and .set()instead of x[y].
但在这种情况下,我认为使用 Map 没有任何好处,除了用.get()和.set()而不是x[y].
回答by Francis Leigh
Seems a bit of a long way round but if you spread the map out and apply it to a new Mapyour component will re-render. I think using a Object reference instead of a Mapwould work best here.
看起来有点绕,但是如果您将地图展开并将其应用于new Map您的组件将重新渲染。我认为Map在这里使用 Object 引用而不是 a最有效。
const {useState} = React
const Mapper = () => {
const [map, setMap] = useState(new Map());
const addToMap = () => {
const RNDM = Math.random().toFixed(5)
map.set(`foo${RNDM}`, `bar${RNDM}`);
setMap(new Map([...map]));
}
return (
<div>
<ul>
{[...map].map(([v, k]) => (
<li key={k}>
{k} : {v}
</li>
))}
</ul>
<button onClick={addToMap}>add to map</button>
</div>
);
};
const rootElement = document.getElementById("react");
ReactDOM.render(<Mapper />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
回答by rodamn
As a supplement to using a single object to hold the state of numerous items, the updates will not occur as expected if updating multiple items within a single render.Newer commits within the render cycle will simply overwrite previous commits.
作为使用单个对象来保存多个项目状态的补充,如果在单个渲染中更新多个项目,则不会按预期进行更新。渲染周期中较新的提交将简单地覆盖以前的提交。
The solution to this is to batch up all the changes in a single object and commit them all at once, like so:
解决方案是将单个对象中的所有更改批量化并一次性提交,如下所示:
// An object that will hold multiple states
const [myStates, setMyStates] = useState({});
// An object that will batch all the desired updates
const statesUpdates = {};
// Set all the updates...
statesUpdates[state1] = true;
statesUpdates[state2] = false;
// etc...
// Create a new state object and commit it
setMyStates(Object.assign({}, myStates, statesUpdates));

