Gustavo Garcia
Gustavo Garcia

Reputation: 3223

Dynamically (and globally) set input field that is on focus in react-native

I'm developing an IoT/Mobile application. Currently i have a code that receives and decodes a package async from my IoT device. This device connects tools such as scales and other equipments. I need to send this IoT data into input Fields.

The code that manages IoT runs in background, it starts with the application, and runs using callbacks. It manages the connections, reconnections and sets up a callback on package data received. Just for example a package data can contain a single value like: 10.34 This code starts with the application.

On the main app, i have many input fields, numeric and text. When i receive a package from IoT I want to write into the currently focused field.

  1. The user starts an operation in the App, there is a field called Weigth.
  2. The user focus on the field.
  3. The user presses a button on the external IoT device connected to a scale.
  4. The app receives the data (ex. 10.34 kg) into the phone and fires a callback.
  5. The callback sends the 10.34 into the input field for Weight.

Just for example. Imagine that the IoT device is a keyboard, and it can write just the same as the screen keyboard. But the firmware is closed and it uses a low level crazy protocol that can't be converted into a keyboard.

Extra

Injecting KeyboardEvent doesn't work, for safety reasons we cannot inject if we don't know where. Injecting into document (root level) won't work.

My application is currently using Redux (if it helps on solution)

Upvotes: 2

Views: 557

Answers (2)

fils capo
fils capo

Reputation: 316

You can't use CreateRef directly with Redux or Context API. You need to make some complex forwardRef, thus it's considered a bad pattern.

A much better solution will be implement an observer pattern (Detailed tutorial for observer pattern).

  1. The IoT service starts and have an Observer system
  2. The field is focused onFocus attaches into Observer to sync system.
  3. When IoT changes value, the onFocus callback is fired calling the setValue.

The Observable Pattern for IoT. Was edited from tutorial by only allowing a single attach (you cannot update multiple fields with IoT):

/**
 * IoT using Observer Pattern
 * Only a single subscriber is allowed, as only the focused field shoud be updated
 */

let subscriberCb = null;

const  subscribeIoT = (notifyObserver) => {
    subscriberCb = notifyObserver;
};

const  unsubscribeIoT = () => {
    subscriberCb = null;
};

const  updateIoTValue = (newValue) => {
    console.log(newValue);
    if (subscriberCb !== null){
        console.log('updating observer');
        subscriberCb(newValue);
    }
}

export {
    subscribeIoT,
    unsubscribeIoT,
    updateIoTValue
};

The onFocus attachment:

<TextInput type="text" value={value} onChangeText={setValue} onFocus={() => {
    console.log('Focused');
    subscribeIoT( newValue => setValue(newValue.toString()));
}} />

Upvotes: 1

emi
emi

Reputation: 3070

You will need some global data management via the reducer:

  • Add an object to the global store storing each input's value, indexed by their id (for example).
  • Add another value in the store to save the last focused input id.
  • Add to each input a onFocus handler. Whenever is triggered, pass the id to the reducer and save it in the global store.
  • When a IoT action takes place, modify the store value of the last focused input.
  • If you need to let the user manually modify the inputs, add an onChange event listener to each input and fire the reducer to modify the specified input value.

Instead of modifying all inputs renders, I'd rather create a CustomInput abstract component doing all the needed common stuff.

Upvotes: 1

Related Questions