0

Let's say App component is wrapped by bus, which is exported as withBus. Here's pseudo-ish code.

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  handleSomeEvent(e) {
    this.setState({ [e] });
  }

  render() {
    return ( ... );
  }
}

export default withBus(App);

Here, handleSomeEvent is defined in the App component. It invokes setState.

Is it possible for the wrapping component (withBus) to hijack / override, App's setState instance so that every call to this.setState in App is proxied to a method in withBus which does some stuff, then invokes setState back on App?

Important Point

  • App shouldn't have to implement anything for this functionality.

In this example, the objective is to add functionality to setState without mudding up react's API.

MrPizzaFace
  • 7,807
  • 15
  • 79
  • 123
  • Sure, `withBus` can do anything it wants. – Bergi Jan 26 '18 at 14:48
  • @Bergi how exactly would you accomplish this? An example would be really helpful please :) Just to be clear.. I don't want to have to say something like `this.setState = withBus.setState` in App. – MrPizzaFace Jan 26 '18 at 14:54
  • You're essentially doing aspect-oriented programming here (read up on that). `withBus` can either modify `App` (e.g. overwrite `setState`) or return a complete new class (resembling the passed `App`) that does whatever you want. – Bergi Jan 26 '18 at 15:07

1 Answers1

1

Yes, this is perfectly possible:

function withBus(C) {
    const orig = C.prototype.setState;
    C.prototype.setState = function() {
        // do whatever you want here
        return orig.apply(this, arguments);
    };
    return C;
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Gotchas? Many - you have to know what you're doing and what conventions you care about. Also [overwriting things inside the constructor](https://stackoverflow.com/a/21243884/1048572) is considerably more difficult than overwriting prototype methods, [even more so](https://stackoverflow.com/a/31789308/1048572) in ES6. – Bergi Jan 26 '18 at 15:34