0

New to ReactJS with experience in android

I simply set a value to variable on input change and use it in display

But the input freezes and new value is also not applied

I also declared the var msg outside render function so it isn't initialized every time

This is certainly not how react works and i'm doing trivial mistake but it may be so trivial that there are no answers out there

What am i doing wrong

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

import "./styles.css";
var msg = "initial value";

const Message = () => {
  return (
    <div>
      <input
        type="text"
        value={msg}
        placeholder="Enter a message"
        onChange={(e) => {
          alert(e.target.value);
          msg = e.target.value;
        }}
      />
      <p>
        <strong>{msg}</strong>
      </p>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<Message />, rootElement);

Here's a link to live demo

https://codesandbox.io/s/usestate-01-forked-f2vdq?file=/src/index.js:0-543

6
  • Why don't you use useState? You even import it. Commented Oct 14, 2020 at 16:58
  • Because i want to know why is that necessary.In java the above code would work as expected.Why do i really need useState ? Commented Oct 14, 2020 at 16:59
  • 1
    Because if you don't use state the input freezes and new value is also not applied. Commented Oct 14, 2020 at 17:00
  • And this is exactly my question.Why it freezes.If i do this in a normal html js page it'll work too but why not here? Commented Oct 14, 2020 at 17:01
  • If you just change the value of a variable in a "normal" HTML page it will certainly not re-render the value. Commented Oct 14, 2020 at 17:03

3 Answers 3

1

React is not tracking your variable, so you will never see an update. You need to use component state, which will cause React to be aware of it and trigger a render when it changes. I've updated your code to use the useState hook:

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

import "./styles.css";
var msg = "initial value";

const Message = () => {
  const [message, setMessage] = useState(msg);
  return (
    <div>
      <input
        type="text"
        value={message}
        placeholder="Enter a message"
        onChange={(e) => {
          alert(e.target.value);
          setMesage(e.target.value);
        }}
      />
      <p>
        <strong>{msg}</strong>
      </p>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<Message />, rootElement);

We set the initial internal state based on the msg value, and then update that internal state on change, which will cause a re-render

Sign up to request clarification or add additional context in comments.

Comments

1

Nothing has told React that it needs to re-render the component.

The variable has changed, but it isn't watching the variable.

This is what state is for. Changing the state explicitly informs React that it needs to check to see if anything should be updated in the DOM. Define the variable with a state hook.

const Message = () => {
  let [msg, setMsg] = useState("initial value");

  return (
    <div>
      <input
        type="text"
        value={msg}
        placeholder="Enter a message"
        onChange={(e) => {
          alert(e.target.value);
          setMsg(e.target.value);
        }}
      />
      <p>
        <strong>{msg}</strong>
      </p>
    </div>
  );
};

1 Comment

My understanding was that react periodically refreshes the ui even if no component asks it to. Similar to onDraw in android where the view draws itself on canvas. But it seems like if nobody asks react to update,it'll never update itself.But if i dont provide value param to input the screen doesnt freeze.Now how does react know to render ui
0

Typically, variables are contained only within the classes that use them, instead of making a global variable. Full Working Demo of what I am proposing.

The state is a data object that holds whatever an instance of that class needs to work with. You have a message component, so, if we make it store a message in its state, that message value will be used anywhere in the render() function whenever used. So, we can do value={this.state.msg}, as well as <h1>{this.state.msg}</h1>. The state and component lifecycle are key to good ReactJS development.

React is stateful, as we say. If you put value="hello!", it's the same to ReactJS as putting <h1>hello!</h1>. Unless the state says that has changed because of a setState() call, ReactJS sees no reason for anything in the display to change. Only by value={this.state...} and <h1>{this.state....}</h1> are we able to make anything dynamic.

If you make a state like this, notice here we are setting a default...

constructor(props) {
  super(props);
  this.state = {'msg':'Initial Message'};
}

Then in your input, you can display it, like...

<input
    type="text"
    value={this.state.msg}

And also in the display of the value, like...

<strong>{this.state.msg}</strong>

8 Comments

The demo doesnt seem to display the updated value.The freezing is solved though
Oh, woops! Sorry, forgot to click save on that demo, I just updated it now: just needed this <strong>{this.state.msg}</strong>. I also re-added in the 'initial message' you had into the state. Let me know if this helps!
It works now.Can you please explain why the ui doesnt freeze if i dont use state and dont provide default value to input.There i dont even call any setstate so how does react rerenders properly
Hey, Omkar: Sure thing! I updated the demo and my answer with a default value and a better explanation.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.