0

I have a functional React component that, among other things, sets up a Bluetooth connection and sets a device variable. It also sets up a callback listener for when Bluetooth responses come in. The listener needs to access device.

export default function App() {
  const [device, setDevice]... ?
  var deviceVar;
  
  const listener = (data) => {
    // needs device
    console.log(device, deviceVar);
    // 'device' is undefined but 'deviceVar' is correct
  }

  const scan = () => {
    setDevice(...);
    device = ...
    addListener(listener)
  }  
}

Using setState is unreliable because the listener is triggered before (i.e.) device was updated.

What is the correct way to handle this? Is there a more functional/hooks approach?

Note that this question is NOT about using useEffect to provide my own callback on device. It is about an 'external' callback that I can't control the timing of.

2
  • Can you update your question with more details on how you're connecting your device and how addListener is implemented? Also, device = ... would be an anti-pattern, as you should be using setDevice instead. Commented Sep 2, 2021 at 21:16
  • Yes, I know device = ... is an anti-pattern, this is what I'm trying to fix Commented Sep 3, 2021 at 13:26

2 Answers 2

2

If the problem is race condition on updating the device state, then adding subscription in separate useEffect triggered on device change can help:

export default function App() {

  const [device, setDevice] = useState(null);

  useEffect(() => {
     // called after device is updated in "scan"
     addListener(listener);
  }, [device])
  
  const listener = (data) => {
    // needs device
    console.log(device);
  }

  const scan = () => {
    // update device
    setDevice(...);
  }  
}
Sign up to request clarification or add additional context in comments.

1 Comment

The part that's confusing me is that I need to be able to immediately access device in the same function that sets it.
1

If I understood your problem correctly, I think you can do the following:

export default function App() {

  const listener = (device, data) => {
     console.log(device);
  }

  const scan = () => {
     const device = ...;
     addListener(data => listener(device, data));
  }  
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.