0

We are looking to capture all the events(like button clicks and textfield changes) in a react application. The object is to capture are user actions so that further analysis can be done on user behaviour. We don't want to implement google analytics at every component level since the application is very huge and the effort will be more.

So we are capturing events in the root react component using jquery. This provides us the id of that html element responsible for generating the event. Now using this Id we are supposed to identify the react component to which it belongs and the state information present in that react component. Since we deal with table data, when a table cell is edited we get to know that table is edited using jquery, but inorder to derive the cell address (row,column) and other information, we need the local variables stored in that react component.

Hence we are trying to access the react component. Please let me know the efficient way to do this.

I have tried accessing the react fiber using the html id. This process is combersome as the react fiber is a complex structure and all states information might not be present one react fibre example -> if we have 3 nested divs like this

<div id="div-1">
    // header
    <div id= "div-2">
        <div id="div-3">
             //contains a text field
        </div>
    </div>
</div>

If something is edited in div-3 we capture react fiber associated with it, which might not have all the state information. (react fibre associated with div-1 is most likely to have all data).

1 Answers1

0

since react is made up of components, it is difficult to track it at the root level. However, there is another possibility. You could implement your own event system at this point.

First you have to create a context that provides the needed functions for all child components.

import { createContext, useContext } from 'react';

const EventTrackerContext = createContext();

export const useEventTracker = () => {
  return useContext(EventTrackerContext);
};

Using this context we can then provide a function to track the events to all child components.

The root component could now look like this

import { EventTrackerContext } from './EventTrackerContext';

function App() {
  const trackEvent = (event, component, state) => {
    console.log('Event:', event);
    console.log('Component:', component);
    console.log('State:', state);
  };

  return (
    <EventTrackerContext.Provider value={trackEvent}>
      {/* Your application components */}
    </EventTrackerContext.Provider>
  );
}

export default App;

Via the context the function trackEvent is provided at this point. Within this function these events can now be processed (like for example saving them in an api).

In all components that should be tracked, the react internal eventsystem can be used to pass them into the trackEvent function.

import { useEventTracker } from './EventTrackerContext';

function MyComponent() {
  const trackEvent = useEventTracker();
  const [state, setState] = useState({/* your component state */});

  const handleClick = (event) => {
    trackEvent(event, 'MyComponent', state);
    // Handle the click event
  };

  const handleInputChange = (event) => {
    trackEvent(event, 'MyComponent', state);
    // Handle the input change event
  };

  return (
    <>
      <button onClick={handleClick}>Click me</button>
      <input type="text" onChange={handleInputChange} />
    </>
  );
}

At this point, when the button is clicked or when the text in the input field is changed, the talking react internal event function is called.

How granular and at which point how much should be passed can be defined in the trackEvent method. So it would also be possible to define a parameter as an object and fill it with other data depending on the sitation. Like e.g. which table was clicked on

Maik Thiele
  • 505
  • 2
  • 10
  • Yes got the approach, but this needs changes to be made in every component. – akshay hulkuli May 08 '23 at 07:04
  • @akshayhulkuli i'm afraid that's how react works. You could try to intercept and track the events via a higher-order component. However, I think that the special applications like which table or row was clicked will be a bit difficult with that. You can find the reference here: https://legacy.reactjs.org/docs/higher-order-components.html#:~:text=A%20higher%2Dorder%20component%20(HOC,and%20returns%20a%20new%20component. – Maik Thiele May 08 '23 at 07:22
  • @akshayhulkuli or you add the eventlistener in the root component ```js useEffect(() => { // Subscribe to global events window.addEventListener('mousemove', trackEvent); window.addEventListener('click', trackEvent); // Unsubscribe from global events on cleanup return () => { window.removeEventListener('mousemove', trackEvent); window.removeEventListener('click', trackEvent); }; }, []); ``` – Maik Thiele May 08 '23 at 07:24