儿童班:
interface Props {
name: string;
mac: string;
}
export const BluetoothDeviceItem = (Props, { }) => {
const [connectingState, setConnectingState] = useState('not_connected');
useEffect(() => {
stateChangeCallback();
}, [connectingState]);
const { onClick } = Props;
const stateChangeCallback = () => {
switch (connectingState) {
case 'not_connected':
console.log("not_connected!");
break;
case 'connecting':
console.log("connecting!");
break;
case 'connected':
console.log("connected!");
break;
}
}
const wait = async () => {
setConnectingState('connecting');
let ret = await onClick(Props.mac);
}
return (
<IonItem lines="none" class="item-container" onClick={wait} id={Props.mac} >
</IonItem>
);
}
“父级”类(从技术上讲,不是父级,因为元素在不同的类中呈现)
class Bluetooth extends React.Component<{}, {}}> {
scan() {
for(let i = 0; i < 5; i++) { //using a for loop to pretend bluetooth devices are being found
let a = <BluetoothDeviceItem key={i} mac={i.toString()} name={"device_"+i} onClick={this.connect}></BluetoothDeviceItem>
bluetoothDevices.push(a); //bluetoothDevices is a *global*
}
}
connect = (id) => {
bluetoothDevices.forEach(element => {
//access the state of each element
});
}
}
我首先发布了我的代码,以使其更容易解释。
我有两节课。一个是子类(BlueoothDeviceItem)。在这个类中,有一个状态。它可以具有3个值not_connected
,connecting
和connected
。这段代码被简化了,但是这些状态将会更改某些图标和颜色。
然后是“父”类。这与蓝牙代码有关。正如我在评论中提到的那样,我使用for循环假装找到设备。这大大简化了代码。
调用scan
时,每次找到设备时,都会使用名称和MAC地址创建一个新子级(BluetoothDeviceItem)。这些设备中的每一个将默认为未连接。
当您单击一个时,它将使用单击事件来调用父级函数(connect
)。
我相信蓝牙代码的最佳实践是自己做所有事情。这包括断开设备连接等,以免依赖设备断开连接(至少根据文档,对于某些部件,这是一种好习惯)。蓝牙一次仅允许1个连接。这当然意味着当用户尝试连接一个蓝牙设备时,我需要断开当前连接的所有蓝牙设备。
由于我的孩子班级有3个州,所以我认为这些将是最好的用法。当用户连接到设备时,我会遍历所有设备。如果状态为connecting
或connected
,请断开这些设备的连接。
但是,问题在于您无法访问状态,因为它们是该类的私有状态。我也尝试过道具,但道具是只读的,因此我将无法对其进行修改。
我尝试的最后一件事是refs
:
class Bluetooth extends React.Component<{}, {}> {
ref: any;
constructor({}) {
super({});
this.ref = React.createRef();
}
scan() {
for(let i = 0; i < 5; i++) { //using a for loop to pretend bluetooth devices are being found
let a = <BluetoothDeviceItem key={i} mac={i.toString()} name={"device_"+i} onClick={this.connect} elRef={this.ref}></BluetoothDeviceItem>
bluetoothDevices.push(a); //bluetoothDevices is a *global*
}
}
connect = (id) => {
bluetoothDevices.forEach(element => {
this.ref.current.state //doesn't work since it's a DOM element.
this.ref.current.getState() //also doesnt work
});
}
}
同时还将界面更改为:
interface Props {
name: string;
mac: string;
elRef: any;
}
和IonItem可以:
<IonItem lines="none" class="item-container" onClick={wait} id={Props.mac} ref={Props.elRef} >
由于它是DOM元素,所以不能使用this.ref.current.state
。我尝试的最后一件事是:
<IonItem lines="none" class="item-container" onClick={wait} id={Props.mac} ref={Props.elRef} key={Props.mac} {...{"getState": () => console.log(connectingState)}}>
创建一个getter函数以返回状态。这是最接近我需要的状态,它确实返回了状态,但是它依赖于 all 处于相同状态的所有设备进行更改。即如果任何一个设备的状态为not_connected
,则该函数将返回not_connected
。一旦所有设备的状态为connecting
connecting
答案 0 :(得分:1)
您可以在父组件中维护所有子状态。那也将为您简化事情。使用父类中定义的方法将状态传递给事件并处理事件,作为对孩子的支持。
答案 1 :(得分:0)
在React中,当我们必须将数据从父级传递到子级时,我们只是通过props,但是当我们需要在Parent中访问Child的数据时,我们使用回调函数来实现。该函数是在Parent中定义的,它像您一样接受参数。
connect = (id) => {
bluetoothDevices.forEach(element => {
//access the state of each element
});
}
我们在道具中将此回调函数传递给child,而Child则回调该函数以提供像这样的道具。
const { onClick } = Props;
<BluetoothDeviceItem onClick={() => onClick(id)} />
在Child中调用回调并传递参数时。请记住要用作箭头函数,因为否则它将不会接受您想要传递给父级的参数。您的情况是id是参数。