6

So this is a little crazy. There's a web app that I use that is built with React, which has made certain design decisions that I disagree with.

Luckily, the design is actually simple to change exactly the way I want. I can just open the Chrome React devtools and change the props assigned to a specific component.

But I don't want to manually do this every time, that's not worth it. I want to write a (super hacky) personal bit of javascript that I can inject into the page, which modifies the props being passed to this component.

Wondering if anyone knows a simple hack to inject props from outside of React. Perhaps it's possible to hook into whatever mechanism React uses to respond to the devtools?

Molly
  • 1,887
  • 3
  • 17
  • 34
suddjian
  • 1,986
  • 2
  • 16
  • 25

1 Answers1

12

I've found the following code to generally work with the latest version of React.

function updateProps(domElement, newProps) {
  var keys = Object.keys(domElement);
  var instanceKey = keys.filter(prop =>
    /__reactInternalInstance/.test(prop)
  )[0];
  var instance = domElement[instanceKey];

  for (var prop in newProps) {
    if (newProps.hasOwnProperty(prop)) {
      instance.return.stateNode.props[prop] = newProps[prop];
    }
  }
  instance.return.stateNode.updater.enqueueForceUpdate(
    instance.return.stateNode
  );
}

As an example, you can navigate here https://ahfarmer.github.io/calculator/ and paste all of the code below into the Chrome DevTools console:

function updateProps(domElement, newProps) {
  var keys = Object.keys(domElement);
  var instanceKey = keys.filter(prop =>
    /__reactInternalInstance/.test(prop)
  )[0];
  var instance = domElement[instanceKey];

  for (var prop in newProps) {
    if (newProps.hasOwnProperty(prop)) {
      instance.return.stateNode.props[prop] = newProps[prop];
    }
  }
  instance.return.stateNode.updater.enqueueForceUpdate(
    instance.return.stateNode
  );
}

updateProps(document.getElementById("root").childNodes[0].childNodes[0], { value: 9000 });

The calculator's value will be programmatically updated to 9000.

As a rule of thumb, you want to target the topmost DOM element being rendered in the React component.

// React component
class Application extends React.Component {
  render() {
    return <div id="myapp">Hello {this.props.name}</div>;
  }
}

// Your javascript code
updateProps(document.getElementById("myapp"), { name: 'Jane' }));

You may need some additional hacking to make this work with your specific use case. It's just a matter of figuring out which React internal properties to manipulate.

Also you can use jQuery to make targeting the elements easier.

Edward
  • 716
  • 5
  • 6