Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update value of an element in React component from iOS UIWebView

I am trying to transfer data from native iOS app to a React (not react-native) web app running in a UIWebView.

I get a string from native viewcontroller and need to "inject" it into the value of an <input> element inside a React component class. I gave the element an id like so:

render() {
<div>
...
    <input id="iccid" type="text" name="iccid" pattern="\d*" onChange={this.iccidChanged.bind(this)} autoFocus />
...
</div>
}

Then using JavaScriptCore from iOS (Swift code) I run:

self.context = self.webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as? JSContext
self.context!.evaluateScript("document.getElementById('iccid').value='\(barcodeValue)';") 

This seems work fine and I can see the value updated in the DOM inside the webview, problem is that my React onChange function (that validates the value and changes component state) does not fire as React does not interpret this as a change (probably because of DOM vs virtual DOM handling).

What's the correct way/best practice to update the element value from iOS AND get the React component to behave like user has typed it in?

like image 870
mindbomb Avatar asked Dec 04 '15 03:12

mindbomb


People also ask

How to update the UI of an element in react?

Once you create an element, you can’t change its children or attributes. An element is like a single frame in a movie: it represents the UI at a certain point in time. With our knowledge so far, the only way to update the UI is to create a new element, and pass it to ReactDOM.render (). Consider this ticking clock example:

What are elements in React DOM?

Unlike browser DOM elements, React elements are plain objects, and are cheap to create. React DOM takes care of updating the DOM to match the React elements. One might confuse elements with a more widely known concept of “components”. We will introduce components in the next section.

How to edit an item in a list in ReactJS?

So far, the list is just a JavaScript variable and not stateful yet. In order to modify it, in this case to edit an item in it, we need to make the list stateful with React's state and its useState Hook: Now we have a stateful list and we are able to alter it.

What is an element in react rendering?

Rendering Elements. Elements are the smallest building blocks of React apps. An element describes what you want to see on the screen: const element = <h1>Hello, world</h1>; Unlike browser DOM elements, React elements are plain objects, and are cheap to create. React DOM takes care of updating the DOM to match the React elements. Note:


1 Answers

I'm supposing that you want to trigger an event when a barcode is scanned. Your iOS app probably doesn't need to know where the event should be dispatched (i.e. which input field and how). It should be enough just to signal the web view that a barcode has been scanned.

You can dispatch a custom DOM event to window and have some React component listen to that event.

window.dispatchEvent(new CustomEvent('barcodescan', {
  detail: {
    value: '(barcodeValue)'
  }
}))

You can then create a non-rendering component that will listen to the barcode event:

const BarcodeListener = React.createClass({
  propTypes: {
    onBarcodeScan: React.PropTypes.func.isRequired
  },
  componentDidMount () {
    window.addEventListener('barcodescan', this.handleBarcodeScan)
  },
  componentWillUnmount () {
    window.removeEventListener('barcodescan', this.handleBarcodeScan)
  },
  render () {
    return null
  },
  handleBarcodeScan (e) {
    this.props.onBarcodeScan(e)
  }
})

Then, in your form, you can render the input alongside with the barcode event listener:

  render () {
    return (
      <div>
        ...
        <input ... />
        <BarcodeListener onBarcodeScan={this.handleBarcodeScan} />
      </div>
    )
  }

Then handle the barcode scan event separately.

like image 100
Thai Avatar answered Sep 21 '22 15:09

Thai