Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply style "cursor: pointer" to all React components with onClick function

I would like to apply the style cursor:pointer to all React elements that have an onClick function. I know I could do this to every element:

<a onClick={handleClick} style={{cursor:'pointer'}}>Click me</a>

or this:

<a onClick={handleClick} className="someClassWithCursorPointer">Click me</a>

But I'd much rather be able to just do something like this to apply the style to all elements:

<style>
 [onclick] {
   cursor: pointer; 
  }
</style>

But that won't work because there's no actual onclick attribute in the rendered HTML of an element when using React's onClick attribute.

Fiddle: https://jsfiddle.net/roj4p1gt/

like image 392
chevin99 Avatar asked Jan 08 '16 15:01

chevin99


1 Answers

I am not certain there's a good way to do this automatically without using some sort of mechanism that intercepts the creation of React elements and modifies them (or perhaps source level transforms). For example, using Babel, you could use babel-plugin-react-transform and add a className to all elements with an onClick prop using something along these lines (warning: pseudocode):

export default function addClassNamesToOnClickElements() {
  return function wrap(ReactClass) {
    const originalRender = ReactClass.prototype.render;

    ReactClass.prototype.render = function render() {
      var element = originalRender.apply(this, arguments);
      return addClickClassNamesToApplicableElements(element);
    }

    return ReactClass;
  }
}

function addClassNamesToApplicableElements(elem) {
  if (!elem || typeof elem === "string") return elem;

  const children = elem.children;
  const modifiedChildren = elem.props.children.map(addClassNamesToApplicableElements);

  if (elem.props.onClick) {
    const className = elem.props.className || "";

    return {
      ...elem,
      props: {
        ...elem.props,
        className: (className + " hasOnClick").trim(),
        children: modifiedChildren
      }
    };
  } else {
    return {
      ...elem,
      props: {
        ...elem.props,
        children: modifiedChildren
      }
    }
  };
}

Here's a quick example of the second part working: https://bit.ly/1kSFcsg

like image 118
Michelle Tilley Avatar answered Nov 01 '22 03:11

Michelle Tilley