0
import React, { useState } from "react";

function App() {
  const [fName, setfName] = useState("");

  function changefName(event) {
    setfName(event.target.value);
  }

  return (
    <div className="container">
      <h1>
        Hello {fName}
      </h1>
      <form>
        <input
          name="fName"
          placeholder="First Name"
          onChange={changefName}
          value={fName}
        />
        <button>Submit</button>
      </form>
    </div>
  );
}

What can happen if I don't declare value={fName} in my input tag? I understand the difference between controlled and uncontrolled component from this post, but I don't understand the significance if I don't declare whether it is controlled or uncontrolled.

Full code here: https://codesandbox.io/s/changing-complex-state-forked-llfq2f?file=/src/components/App.jsx

chu-js
  • 181
  • 7
  • 2
    I don't think its a matter of declaration, but a matter of usage. Do you want react to manage the state, or do you want to set the state with a ref, or regular javascript. – WPW Sep 19 '22 at 14:58
  • If you don't declare it as controlled, the state is going to be managed/driven by the browser default DOM state, in other words, you won't have control over the input state(on Change, keystrokes, etc). – Abdulrahman Ali Sep 19 '22 at 14:59
  • But doesn't ```function changefName(event) {setfName(event.target.value);}``` manage the input state? – chu-js Sep 19 '22 at 15:00
  • 1
    @chu-js It does, because `setFName` is a React state. If you don't want to use React driven state, you can use the DOM default state with a `ref`. Check @CertainPerformance's answer. It's what you are looking for. – Abdulrahman Ali Sep 19 '22 at 15:07

2 Answers2

2

If you do not use a value prop, the input is uncontrolled. Although you have an onChange handler, the value of the input is managed only from the DOM, so your fName state may not necessarily be the same as the value in the input. For example, if you call setFName elsewhere - outside the onChange - the input in the DOM will not reflect the state change.

For example, the button below does not result in the input value changing:

function App() {
  const [fName, setfName] = React.useState("");

  function changefName(event) {
    setfName(event.target.value);
  }

  return (
    <div className="container">
      <button onClick={() => setfName('foo')}>Change name to foo</button>
      <h1>
        Hello {fName}
      </h1>
      <form>
        <input
          name="fName"
          placeholder="First Name"
          onChange={changefName}
        />
        <button>Submit</button>
      </form>
    </div>
  );
}

ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div class='react'></div>

It's best to choose one approach and stick with it, for a particular state and input: either have a value and an onChange that maps to that state value, or don't have either. (You can still have an onChange in an uncontrolled component - just don't have it change a state text value too, otherwise you could easily run into bugs like in the snippet above.)

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
0

Nothing, it will set the input tag's default value and controller. You will no longer have the input state change, it will be a declared but unused hook (fname).

But the onchange event will still be called and populated within your function (changefName), see that it takes the target.value, which is the value of the input (which has its own controller).