1

In React JSX vs function call to present component the question was answered with 'no' when it comes to a difference between function call or (tag) component.

Here I have a confusing example where the difference between function call and tag is leading to a change in focus behaviour. I am sure there are React experts out there with a reasonable explanation - unfortunately I am not yet there ;-)

Here the code with the commented differences between tag and function call:


import React, {useState} from 'react';

function FocusRiddle() {

    const [currentRow, setCurrentRow] = useState({firstName: 'Barack', lastName: 'Obama'});

    // This keeps the focus correctly
    return <div>{Att()}</div>;

    // This loses the focus after every letter !!!
    // return <div><Att /></div>;

    function Att() {
        return <div>
            <h1>Welcome to Focus Riddle</h1>
            <div>
                <MyInput key={'firstName'} name={'firstName'} row={currentRow} action={updateRow}/>
            </div>
            <div>
                <MyInput key={'lastName'} name={'lastName'} row={currentRow} action={updateRow}/>
            </div>
            <div>
                <button onClick={() => alert(JSON.stringify(currentRow))}>Show Row</button>
            </div>
        </div>
    }


    function updateRow(name, value) {
        setCurrentRow({...currentRow, [name]: value});
    }

}

function MyInput({name, row, action}) {
    return <input
        value={row[name]}
        onChange={(event) => action(name, event.target.value)}/>
}

export default FocusRiddle;
Toni Bünter
  • 93
  • 1
  • 6

1 Answers1

1

Calling Att() is equivalent to implementing a normal component, as you just declared a function and called it in components scope.

So nothing special here, the state should persist:

function FocusRiddle() {
  const [currentRow, setCurrentRow] = useState({
    firstName: "Barack",
    lastName: "Obama",
  });

  function updateRow(name, value) {
    setCurrentRow({ ...currentRow, [name]: value });
  }

  return (
    <div>
      <div>
        <h1>Welcome to Focus Riddle</h1>
        <div>
          <MyInput
            key={"firstName"}
            name={"firstName"}
            row={currentRow}
            action={updateRow}
          />
        </div>
        <div>
          <MyInput
            key={"lastName"}
            name={"lastName"}
            row={currentRow}
            action={updateRow}
          />
        </div>
        <div>
          <button onClick={() => alert(JSON.stringify(currentRow))}>
            Show Row
          </button>
        </div>
      </div>
    </div>
  );
}

But, on calling <Att/> you create React Element, because using JSX syntax is a sugar syntax for React.createElement. See JSX in depth.

So with it, React elements's aware of props change and render when their parent is rendered.

When you typing in input and calling setCurrentRow, FocusRiddle gets rendered, and Att component unmounts (because you re-declare Att component on every render) therefore you lose focus.

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118