【发布时间】:2020-03-26 05:34:16
【问题描述】:
我有一个 React 组件,它循环遍历数据数组并为数组中的每个对象呈现一个复选框。
"supplies": [{
"deviceName": "OMEGAX d3241",
"productName": "ZA1239",
"productGroup": "hearing aid batteries",
"productId": "1",
"lastOrderDate": "2020-01-01",
"nextAvailabilityDate": "2020-09-01",
"quantity": 60
},
{
"productGroup": "hearing aid accessories",
"productId": "3",
"availableForReorder": true,
"lastOrderDate": "2019-06-30",
"nextAvailabilityDate": "2019-12-15",
"quantity": 10,
"size": "6mm"
},
{
"productName": "DOME",
"productGroup": "hearing aid accessories",
"productId": "4",
"availableForReorder": true,
"lastOrderDate": "2019-06-30",
"nextAvailabilityDate": "2019-12-15",
"quantity": 10,
"size": "7mm"
},
{
"productName": "WaxBuster Single Unit",
"productGroup": "hearing aid accessories",
"productId": "5",
"availableForReorder": true,
"lastOrderDate": "2019-06-30",
"nextAvailabilityDate": "2019-12-15",
"quantity": 10
}
]
大部分数据显示在 React 类组件
class SelectArrayItemsWidget extends React.Component {
state = {
checkedSupplies: new Map(),
};
componentDidMount() {
this.props.getReOrderBatteryAndAccessoriesInformationData();
}
handleChecked = e => {
const supply = e.target.name;
const isChecked = e.target.checked;
this.setState(prevState => ({
checkedSupplies: prevState.checkedSupplies.set(supply, isChecked),
}));
};
render() {
const { supplies } = this.props;
const { isChecked, checkedSupplies } = this.state;
return supplies.map(supply => (
<div key={supply.productId} className="order-background">
<p className="ds-u-font-size--md ds-u-font-weight--bold">
{supply.productName}
</p>
<div className="ds-u-border-left--10px ds-u-border-color--primary-alt">
<div className="usa-alert-body mdot-alert-body">
<p className="ds-u-margin--1px">
<span className="ds-u-font-weight--bold">Battery: </span>
{supply.productId}
</p>
<p className="ds-u-margin--1px">
<span className="ds-u-font-weight--bold">Quantity: </span>
{supply.quantity} <br />
Approximately {supply.quantity} months supply
</p>
<p className="ds-u-margin--1px">
<span className="ds-u-font-weight--bold">Last order date: </span>{' '}
{moment(supply.lastOrderDate).format('MM/DD/YYYY')}
</p>
</div>
</div>
<div
className={
!isChecked
? 'ds-u-background-color--white ds-u-color--link-default button-dimensions ds-u-border-color--primary ds-u-border--2px'
: 'ds-u-background-color--primary button-dimensions ds-u-color--white ds-u-border-color--primary ds-u-border--2px'
}
>
<input
name={supply.productId}
checked={!checkedSupplies.get(supply.productId)}
type="checkbox"
onChange={this.handleChecked}
/>
<label htmlFor={supply.productId} className="main">
Order batteries for this device
</label>
</div>
</div>
));
}
}
我希望每个复选框的包装 div 更改文本颜色和背景颜色,具体取决于是否选中了单个复选框。我在容器上运行一个条件:
!isChecked
? 'vads-u-background-color--white vads-u-color--link-default button-dimensions vads-u-border-color--primary vads-u-border--2px'
: 'vads-u-background-color--primary button-dimensions vads-u-color--white vads-u-border-color--primary vads-u-border--2px'
但是,每次选中复选框时,容器都不会更改其样式属性。
【问题讨论】:
-
我认为这里的主要问题是
state.checkedSupplies是 Map 的实例,而Map.prototype.set始终返回相同的映射,即在执行突变后引用自身。 React 运行时比较先前和当前状态,发现两者相等,因此不会更新 DOM。要解决此问题,请考虑使用普通对象而不是 Map,或者可能仍使用 Map 但将其更新设为不可变操作。 -
如果你想使用不可变版本的
Map、Set等,还有不可变的 (immutable-js.github.io/immutable-js)。不过,它是一个大包。
标签: javascript html css reactjs