How I Connected React Components to External JS: A Developer’s Story

Published on
2 mins read
--- views

Due my current work task i have a case - to call a modal created as a React-component from SharePoint Ribbon. In two words, SharePoint ribbon is a structure that contains buttons and js-functions binded for it. When you push the button, js function binded for it calls... hope you understand :). And i started to google: how to interact with react module from outer js, how to change react state from outer js, force re-render react component from pure js and so on... So, the main problem is: you cannot bind react-component function to ribbon button because it hides deep inside into webpack js bundle. Also, i need to change React Module state because i want rerender component when i click the button. So, i make the fiddle and looks like it works correctly - https://jsfiddle.net/o6ujb5g2/. It is not SharePoint ribbon, but almost the same. Idea is to attach function from react modal to global window object. This object exist from almost anywhere.

Steps:

  1. I created a stub-function in pure js for window.func that i want to override from component (it is for safety, if some problems with component will happens due it's render)
  2. In component i initialize a func with business logic, that changes component state
  3. On componentDidMount i override global window.func to module.func
  4. PROFIT!!!

Source Code listings:

HTML
<script>
window.toggleModal = function(isOpened) {
  console.log(`[x] Loading... Passed value: ${isOpened}`);
}
</script>


<input type="button" onclick="js:window.toggleModal(true);" value="click me"/>
<div id="app" var1="test"></div>
React Module
class TodoApp extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      isModalOpened: false,
      items: [
        { text: Learn JavaScript, done: false },
        { text: Learn React, done: false },
        { text: Play around in JSFiddle, done: true },
        { text: Build something awesome, done: true }
      ]
    }
  }

  componentDidMount = () => {
    window.toggleModal = this.toggleModal;
  }

  toggleModal = (isOpened) => {
    this.setState({
      ...this.state, isModalOpened: isOpened
    });
  }

  render() {
    return (
      <div>
        <h2>Todos:</h2>
        <ol>
        {this.state.items.map(item => (
          <li key={item.id}>
            <label>
              <input type=checkbox disabled readOnly checked={item.done} />
              <span className={item.done ? done : }>{item.text}</span>
            </label>
          </li>
        ))}
        </ol>
        {this.state.isModalOpened && (
        <React.Fragment>
          <p>modal opened!</p>
          <input type=button onClick={() => this.toggleModal(false)} value=close />
        </React.Fragment>)}
      </div>
    )
  }
}

ReactDOM.render(<TodoApp />, document.querySelector(#app))