我是使用 React 和 Recoil 的新手,我想从使用Web Bluetooth API实时收集的数据中显示实时图表(使用 D3)。
简而言之,在调用await myCharacteristic.startNotifications()
and之后myCharacteristic.addEventListener('characteristicvaluechanged', handleNotifications)
,handleNotifications
每次从蓝牙设备通知新值时都会调用回调(请参阅此示例)。
我正在使用钩子并尝试从回调中修改后坐力状态(这被简化到了极致,我希望它具有代表性):
export const temperatureState = atom({
key: 'temperature',
default: 0
})
export function BluetoothControls() {
const setTemperature = useSetRecoilState(temperatureState);
const notify = async () => {
...
temperatureCharacteristic.addEventListener('characteristicvaluechanged', event => {
setTemperature(event.target.value.getInt16(0))
}
}
return <button onClick={nofity}/>Start notifications</button>
}
如果我想在应用程序的某处显示最新值,这可以正常工作。但是,我有兴趣将最后几个(比如说 10 个)值保留在循环缓冲区中以绘制 D3 图表。
我尝试了一些类似的东西:
export const temperatureListState = atom({
key: 'temperature-list',
default: []
})
export function BluetoothControls() {
const [temperatureList, setTemperatureList] = useRecoilState(temperatureListState);
const notify = async () => {
...
temperatureCharacteristic.addEventListener('characteristicvaluechanged', event => {
let temperatureListCopy = temperatureList.map(x => x);
temperatureListCopy.push(event.target.value.getInt16(0))
if (temperatureListCopy.length > 10)
temperatureListCopy.shift()
setTemperatureList(temperatureListCopy)
}
}
return <button onClick={nofity}/>Start notifications</button>
}
但是,很明显,我遇到了此处描述的问题,其中该函数使用的temperatureList
是在渲染期间捕获的旧版本。结果,temperatureState
始终为空,然后替换为一个元素的列表。
如何在从外部回调更新的 React 状态/Recoil atom 中维护一致的列表?我认为这个问题有点相似,但我想避免使用像 Recoil Nexus 这样的另一个扩展。