Lost input focus on hooks function state change
Asked Answered
L

1

9

When i define the hooks state in the parent function i lost input field focus on first key press. I need the state definition in the root function.

import React, { useState } from 'react'

function Test1(props) {
    const [test, setTest] = useState({value1: "", value2:""});

    const Test = () => {

        const handleChange= (e) => {
            const _test = {...test, [e.target.name]: e.target.value}
            setTest(_test)
        }

        return (
            <div style={{ margin: "200px" }}>
                <input name="value1" value={test["value1"]} onChange={handleChange}></input>
                <input name="value2" value={test["value2"]} onChange={handleChange}></input>
                <button onClick={() => console.log(test)}>Console.Log</button>
            </div>
        )
    }


    return (
        <Test />
    );

}


export default Test1;

But if I move the state definition in to the child function it works.


import React, { useState } from 'react'

function Test1(props) {

    const Test = () => {
        const [test, setTest] = useState({value1: "", value2:""});

        const handleChange= (e) => {
            const _test = {...test, [e.target.name]: e.target.value}
            setTest(_test)
        }

        return (
            <div style={{ margin: "200px" }}>
                <input name="value1" value={test["value1"]} onChange={handleChange}></input>
                <input name="value2" value={test["value2"]} onChange={handleChange}></input>
                <button onClick={() => console.log(test)}>Console.Log</button>
            </div>
        )
    }


    return (
        <Test />
    );

}


export default Test1;

So! Why is this happening and how can I get over it?

Latoya answered 12/4, 2019 at 14:13 Comment(1)
Can someone explain why one works and other does not?Inflatable
P
16

I have been seeing this pattern a lot where people nest components in methods in components. It may be an opinion, but I feel like this may not be a great pattern.

I would abstract the one component function and pass the props down to the 2nd. something like this

const Test = ({test, setTest}) => {

  const handleChange= (e) => {
      const _test = {...test, [e.target.name]: e.target.value}
      setTest(_test)
  }

  return (
      <div style={{ margin: "200px" }}>
          <input name="value1" value={test["value1"]} onChange={handleChange}></input>
          <input name="value2" value={test["value2"]} onChange={handleChange}></input>
          <button onClick={() => console.log(test)}>Console.Log</button>
      </div>
  )
}

function Test1(props) {
    const [test, setTest] = useState({value1: "", value2:""});


    return (
        <Test test={test} setTest={setTest} />
    );

}


export default Test1;

Prairial answered 12/4, 2019 at 14:21 Comment(5)
Thank you Beualne. This approach solves the problem.Latoya
One more question: If i have too many sub components, it's not feel good the abstract them all with props pass. this is where states advantages comes on, am i wrong?Latoya
this does not work for me... I have the same problemIshmael
I have the same problem with nested components. That's not work for mePrevost
This approach solves the problem for me as well, but is there a justification why it does not work the other wayOvershadow

© 2022 - 2024 — McMap. All rights reserved.