【问题标题】:"Synchronous" useState without useEffect没有 useEffect 的“同步”useState
【发布时间】:2021-11-19 17:06:58
【问题描述】:

我有一个检测到的蓝牙设备列表,deviceList,它是用useState 设置的:

const [deviceList, setDeviceList] = useState([]);

我有一个启动设备扫描的按钮。每次扫描开始时,我都需要将设备列表重置为[]。我愿意:

const scanForDevices = () =>  {
    setDeviceList([]);

    manager.startDeviceScan(null, null, (error, device) => {
        // add device to device list
        setDeviceList(old => [...old, device]);
    }
}

问题是setDeviceList 不是同步的,并且deviceList 在应该添加新设备时没有重置。这可能会导致重复的设备。我可以通过过滤来防止重复,但这只是对实际问题的一种破解。

我不能使用 useEffect 来解决这个问题,所以请不要建议它。 startDeviceScan 不能在每次deviceList 更改时运行。

在没有真正原子的setState 的情况下如何解决这种情况?

【问题讨论】:

  • 在您提供的实现中,manager.startDeviceScan 似乎一次只添加一个设备。是这样吗?
  • @fgkolf 没错
  • 所以如果setState 像你所说的那样是原子的,那么你总是会得到一个包含一个设备的数组,因为old 将是一个空数组。
  • 那么正确的解决方案是什么?
  • 忽略旧状态和setDeviceList([device]); 但我不确定这是您想要实现的目标。

标签: reactjs react-hooks


【解决方案1】:

如果您尝试清除列表并且startDeviceScan 返回多个设备,您似乎可以创建一个临时变量来构建列表,然后在完成时设置状态。

const scanForDevices = () =>  {
    const devices = [];

    manager.startDeviceScan(null, null, (error, device) => {
        // add device to device list
        devices.push(device);
    }

    setDeviceList(devices);
}

【讨论】:

  • 有趣的想法,但 startDeviceScan 直到用户操作才完成。
【解决方案2】:

您是否尝试过使用useReducer 挂钩来更改您的状态?我没有尝试用这个钩子解决像你这样的时间问题,但值得一试。

解决方案可能看起来像这样(未经测试):

const initialState = []
const reducer = (state, {type, payload}) => {
  switch (type) {
    case 'RESET':
      return initialState
    case 'ADD_DEVICE':
      return [...state, payload]
    default:
      return state
  }
}
const [deviceList, dispatch] = useReducer(reducer, initialState)

...

const scanForDevices = () =>  {
  dispatch({type: 'RESET'})

  manager.startDeviceScan(null, null, (error, device) => {
    // add device to device list
    dispatch({type: 'ADD_DEVICE', payload: device})
  }
}

【讨论】:

  • 不幸的是,我的理解是useReducer 也不是同步的,事实上useState 在后台使用useReducer
  • @T3db0t 是的,也是异步的。我只是在想它可能会按顺序进行更新,就像 Redux 使用它的 reducer 所做的那样。
猜你喜欢
  • 2021-10-24
  • 2021-01-27
  • 2022-12-08
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 2021-08-28
  • 1970-01-01
  • 2019-04-12
相关资源
最近更新 更多