Confusion with ReactDom

from the article " How State Works in React – Explained with Code Examples" on this website:

I’m trying to understand how Reactjs render data to the DOM:
I was expecting the following two programs (Program N1. and Program N2.) to give the same results. Actually the Program N1 is printing to the console and also render to the DOM, but Program N2 is only printing to the console but not rendering to the DOM.

would you please help understand why they are not giving the same results

Program N1.

import React from "react";
import ReactDOM from "react-dom";

const rootElement = document.getElementById("root");

let counter = 0;

const handleClick = () => {
  counter++;
  console.log("counter", counter);
  renderContent();
};

const renderContent = () => {
  const content = (
    <div>
      <button onClick={handleClick}>Increment counter</button>
      <div>Counter value is {counter}</div>
    </div>
  );

  ReactDOM.render(content, rootElement);
};

renderContent();

Program N2.

import React from "react";
import ReactDOM from "react-dom";

const rootElement = document.getElementById('root')

let counter = 0;

const handleClick = () => {
  counter++;
  console.log("counter", counter);
  ReactDOM.render(content, rootElement)
};

const content = (
  <div>
    <button onClick={handleClick}>Increment counter</button>
    <div>Counter value is {counter}</div>
  </div>
);
ReactDOM.render(content, rootElement)

Look

const content = (
  <div>
    <button onClick={handleClick}>Increment counter</button>
    <div>Counter value is {counter}</div>
  </div>
);

You’re declaring a variable.

let counter = 0;

const content = counter;

function increment () {
  counter++;
}

increment()
// `counter` is 1
// `content` is still 0!
increment()
// `counter` is 2
// `content` is still 0!

Edit:


You’re not really using React. Or at least you’re not using at all as it’s supposed to be used.

  • JSX isn’t React
  • it’s just a way of writing a load of [nested] functions in <A><Syntax><Like><This>. - Each one of those tokens gets converted to the function by a compiler: TypeScript, Babel are examples of compilers: they take some code that isn’t quite JavaScript and compile it to JavaScript.
  • The library you use defines what function the JSX gets converted to.
  • in the case of React, it’s a function called createElement (well, to be be more precise, it’s a function called jsx, which then may get converted to createElement if necessary by ReactDOM).
  • you don’t need JSX, you can always just use React.createElement directly
  • Those nested functions get passed to a rendering library
  • for React, there is ReactDOM for the DOM and React Native for Android/iOS. There are lots of others people have built which are not widely used, for example: React Sketch, React ART, React-Three-Fiber, React-CLI.
  • The rendering library renders to the target (DOM for React DOM, Android/iOS for React Native, etc.)

So you use React to write code to manipulate that model, then you pass it to that other program (ReactDOM here).

But you shouldn’t manually run ReactDOM every single time you want to update anything: if you do that, then you might as well just use the DOM APIs and do it all yourself, or use jQuery or whatever. You just need to run it once.

What you’re doing is rendering some JSX using your renderContent() function. Then when a button gets clicked, you are adjusting a global variable, and rerendering everything. And when it’s clicked again, you rerender again. It’s basically the same as writing this (if you paste this in a file like example.html and open in a browser, it’ll do the same thing):

<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title>blah</title>
</head>
<body>
<button id="counterButton">Increment counter</button>
<p>Counter value is <span id="counterDisplay">0</span></p>
    
<script>
let counter = 0;

counterButton.addEventListener("click", () => {
    counterDisplay.innerHTML = ++counter;
});
</script>

You’re just using it as a glorified way of writing JS templates. ReactDOM already does this. You only need to pass it the entry point of your app, the entire point is that is that you don’t need to manually rerender things every time something changes. So like

import { useState } from "react";
import ReactDOM from "react-dom";

const rootElement = document.getElementById("root");

const Content = () => {
  const [counter, setCounter] = useState(0);

  const handleClick = () => {
    setCounter(counter + 1);
  };

  return (
  <div>
    <button onClick={handleClick}>Increment counter</button>
    <div>Counter value is {counter}</div>
  </div>
  );
};

ReactDOM.render(<Content/>, rootElement);

I got it. Thanks too much Dan, for you time.

1 Like

It’s slightly hard to grok if you come to it assuming render is something you need to run manually – like if you’ve played around with using the DOM APIs or jQuery or whatever, where you need to tell it to do everything. But in this case it’s a lot simpler than that (though it does a lot more magic under-the-hood): you build your app in React, then you hand ReactDOM.render() your app, and off you go – generally there wil only be one render call in your entire codebase, and normally that’s the only place you use ReactDOM.

Sure! I’m Just trying to learn React as beginner.

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.