2

I am fairly new to React and I am trying to understanding the difference between the following:

let stateChange = new MyComponentButton();
ReactDOM.render(stateChange.render(),
document.getElementById('state_change_component_jsx'));

and

ReactDOM.render(<MyComponentButton/>,
document.getElementById('state_change_component_jsx'));

Essentially, if someone clicks the button. The text updates from Initial State to React Rocks. The component would initialize with the initial state being 'Initial State' and when someone clicks on the button, handleClick() gets triggered, updating the initial state with the use of setState to a different state called 'React Rocks!'. But what I got stuck for a long time initially was that, when my code was

let stateChange = new MyComponentButton();
ReactDOM.render(stateChange.render(), document.getElementById('state_change_component_jsx'));

I would get an error/warning when I click the button as follows:

 > Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the MyComponentButton component.

However, if I were to 'mount' the component properly by doing this:

ReactDOM.render(<MyComponentButton/>, document.getElementById('state_change_component_jsx'));

The code would work perfectly. My question is, why is this the case and why creating an instance of the component wouldn't properly mount the component. My understanding is that creating an instance of the component should be the same as mounting a component. Would appreciate any explanation or a link for me to enforce my understanding.

I've tried doing and reading the following links:

  1. Can't call setState on a component that is not yet mounted (did not really helped in my understanding of why this was the case but it had a similar error/warning message)

I tried reading through some of the links from React's official page

  1. https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html

  2. https://reactjs.org/docs/react-component.html

  3. https://reactjs.org/docs/react-component.html#setstate

  4. https://reactjs.org/docs/components-and-props.html

The code that I have is as follows for reference: HTML file

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

  <!-- We will put our React component inside this div. -->
  <div id="state_change_component_jsx"></div>

  <!-- Load React. -->
  <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
  <script src="https://unpkg.com/prop-types@15.6/prop-types.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>

  <!-- Load our React component. -->
  <script src="/practice.js" type="text/babel"></script>

</body>
</html>

JavaScript file

class MyComponentButton extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      name: 'Initial State'
    };

    // binds function to component I think
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState({
      name: 'React Rocks!'
    })
  }


  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click Me</button>
        <h1>{this.state.name}</h1>
      </div>
    );
  }
};

ReactDOM.render(<MyComponentButton/>, document.getElementById('state_change_component_jsx'));

1 Answers1

1

You describe the JSX and React mounts the component and handles all the lifecycle, including calling render. You should never be calling React component lifecycle methods yourself directly.

In the case of

let stateChange = new MyComponentButton();
ReactDOM.render(
  stateChange.render(), 
  document.getElementById('state_change_component_jsx'),
);

You're calling the render method directly, but React has yet to process and mount the component, i.e. componentDidMount hasn't been called yet to essentially say "ok, the component is mounted and renderable."

With

ReactDOM.render(
  <MyComponentButton/>,
  document.getElementById('state_change_component_jsx'),
);

You are passing the JSX that describes what you want React to do and it handles instantiating and mounting the component, making it ready to render.

React without JSX may shed a bit of light on what is happening behind the scenes, but gist is:

Each JSX element is just syntactic sugar for calling React.createElement(component, props, ...children). So, anything you can do with JSX can also be done with just plain JavaScript.

So you can use plain vanilla Javascript to render your component, but you still don't instantiate it directly yourself.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181