DEV Community

Niya Panamdanam
Niya Panamdanam

Posted on

Using Custom Events to communicate between legacy jQuery code and new Framework code

This is an updated version of one my older blogs: Old Post

While writing a new feature using React one of my hurdles was figuring out a way to make the new React code and the old jQuery code communicate with each other. My new component, had to get date and time from the date picker written in jQuery code as users interacted with it. At this time I didn’t have the option to rewrite the date picker in React.

My solution to this problem was to use Custom Events.
The custom event was setup in the jQuery function to dispatch every time it returned a result. Then I setup the React component to listen for this custom event and update state.

Let’s Look At Some Code Samples

The React Component:

const MyComponent ()=> {
    const [dateRange, setDateRange] = useState({from:'', to:''})

    return <div id='containerId' />
}
Enter fullscreen mode Exit fullscreen mode

This component renders a div with an id that I will need for the jQuery to use. My state object has the keys from and to that needs the date and time information from the jQuery date picker.

Part of jQuery Code handling the DatePicker:

setDateTime: function() {
  var from = moment(picker.from).utcOffset(this.utcOffset());
  var to = moment(picker.to).utcOffset(this.utcOffset());

  this.setView(from, to);
}
Enter fullscreen mode Exit fullscreen mode

The above snippet is the small part of a larger file using global variables to trigger the setDateTime function. This then passes the from and to values to other functions in the jQuery file. Functionally the jQuery date picker works well, code wise though its super fragile and impossibly hard to figure how it all connects.

Thankfully the above snippet is all I needed. Every time the setDateTime function was triggered I need it to send the from and to values to my React component.

Adding my custom event:

setDateTime: function() {
  var from = moment(picker.from).utcOffset(this.utcOffset());
  var to = moment(picker.to).utcOffset(this.utcOffset());
  var myEvent = new CustomEvent('dateTimeEvent', 
      { bubbles: true, detail: { dateTime: {from, to} });

    document.querySelector('#containerId').dispatchEvent(myEvent);
  this.setView(from, to);
}
Enter fullscreen mode Exit fullscreen mode

As the from and to are set in the setDateTime function, I have my custom event named myEvent that then bubbles the dateTime object with these values. The event is dispatched to the div with the id='containerId' in my React component. This function does not in any way interfere with the rest of the jQuery code. It just passes the information I need without changing any other existing functionality.

Update the React Component

useEffect(()=>{
  window.addEventListener('dateTimeEvent', 
  onDateTimeChange(e))
},[])
Enter fullscreen mode Exit fullscreen mode

I added the event listener to the useEffect. Any time the setDateTime function in the jQuery is triggered the listener will capture dateTime object and pass it into my function onDateTimeChange.

const onDateTimeChange = (e) => {
   setDateRange({
      from: e.detail.dateTime.from,
      to: e.detail.dateTime.to
   })
}
Enter fullscreen mode Exit fullscreen mode

Every time the onDateTimeChange is triggered it updates state in my React component with the date time value from the jQuery code.

In this way my new React component could coexist with the jQuery date picker without having to worry about the legacy code interfering. Plus the changes to the jQuery code were minimal and didn’t affect any of its existing functions.

What The React Component Looks Like Now

const MyComponent ()=> {
    const [dateRange, setDateRange] = useState({from:'', to:''})

const onDateTimeChange = (e) => {
   setDateRange({
      from: e.detail.dateTime.from,
      to: e.detail.dateTime.to
   })
}

useEffect(()=>{
  window.addEventListener('dateTimeEvent', 
  onDateTimeChange(e))
},[])

    return <div id='containerId' />
}
Enter fullscreen mode Exit fullscreen mode

This was an interim solution that allowed me to continue working on the new feature, without having to do a costly rewrite at the same time.

Top comments (0)