React中如何将新增的单个设备对象推入目标数组devicesList?
问题:React中向数组添加单个设备对象避免嵌套数组
我正在使用React,需要将数组devices中的新增单个设备对象推入currentRoom内的空数组devicesList。devices的控制台输出示例如下:
(2) [Device, Device] 0: Device {deviceName: 'AC', deviceStatus: 'off'} 1: Device {deviceName: 'TV', deviceStatus: 'off'}
我有一个点击触发的函数,期望每次向devices添加新设备时,通过push()将该设备加入devicesList末尾。但使用devicesList.push(devices)会导致嵌套数组,当前输出为:
devicesList: Array(3) 0: [] 1: [Device] Device {deviceName: 'Light', deviceStatus: 'off'} 2: (2) [Device, Device] 0: Device {deviceName: 'Light', deviceStatus: 'off'} 1: Device {deviceName: 'Stereo', deviceStatus: 'off'} length: 3
期望devicesList输出为:
devicesList: Array(3) 0: [] 1: [Device] Device {deviceName: 'Light', deviceStatus: 'off'} 2: [Device] Device {deviceName: 'Stereo', deviceStatus: 'off'} length: 3
相关代码如下:
const [showAdd, setShowAdd] = useState(false); const [deviceName, setDeviceName] = useState('') const [deviceStatus, setDeviceStatus] = useState('off') const [devices, setDevices] = useState([]) const AddNewDevice = (deviceName, deviceStatus) => { //1st step: Validation of the device: let containsStereo = devices.some(e => e.deviceName === 'Stereo') let isBathroom = currentRoom.roomType === 'Bathroom' let devicesList = currentRoom.devicesList if ((containsStereo && deviceName == 'Stereo') || (!isBathroom && deviceName == 'Boiler') || (devicesList.length > 5)) return alert('error') else { //2nd if validated creation of new device const newDevice = new Device(deviceName, deviceStatus); console.log(newDevice); setDevices([...devices, newDevice]) console.log(devices); devicesList.push(devices); console.log(currentRoom); } return devicesList }
解决方案
问题根源
- 嵌套数组原因:执行
devicesList.push(devices)时,是把整个devices数组(包含所有历史设备)推入devicesList,而非刚创建的单个newDevice,导致多层嵌套。 - React状态违规:直接修改
currentRoom.devicesList属于直接变更状态,React无法检测到该变化,不会触发组件重新渲染。
修正代码
假设currentRoom是通过useState声明的状态(const [currentRoom, setCurrentRoom] = useState(...)),修改后的AddNewDevice函数如下:
const AddNewDevice = (deviceName, deviceStatus) => { // 验证逻辑 const containsStereo = devices.some(e => e.deviceName === 'Stereo'); const isBathroom = currentRoom.roomType === 'Bathroom'; const { devicesList } = currentRoom; if ((containsStereo && deviceName === 'Stereo') || (!isBathroom && deviceName === 'Boiler') || (devicesList.length > 5)) { alert('error'); return; } // 创建新设备 const newDevice = new Device(deviceName, deviceStatus); // 更新devices状态:生成新数组添加新设备 const updatedDevices = [...devices, newDevice]; setDevices(updatedDevices); // 更新currentRoom的devicesList:添加单个设备的数组(匹配期望格式) const updatedDevicesList = [...devicesList, [newDevice]]; setCurrentRoom({ ...currentRoom, devicesList: updatedDevicesList }); console.log(updatedDevicesList); return updatedDevicesList; };
关键说明
- 使用扩展运算符(
...)创建新数组,避免直接修改原状态数组,符合React状态不可变原则。 - 向
devicesList中推入[newDevice](单个设备的数组),而非整个devices数组,解决嵌套问题。 - 通过
setCurrentRoom更新房间状态,确保组件能感知到devicesList的变化并重新渲染。 - 原代码中
console.log(devices)会输出旧值(因为setDevices是异步操作),如需查看更新后的值,可直接打印updatedDevices变量,或通过useEffect监听devices状态变化。
内容的提问来源于stack exchange,提问作者Yehoudith Polony
相关产品推荐
相关产品推荐

