Home > database >  Grandparent state is not updating from onFocus in Grandchild in react js?
Grandparent state is not updating from onFocus in Grandchild in react js?

Time:12-13

I have react component like given below:-

Now I have few input fields in child component. I want to update grandparent state when user focus child component input control.

GrandParent Code:-

const GrandParent=()=>
{
  const [focusDiv, setFocusDiv] = useState(false);
  return (
  <>
  <h1>GrandParent</h1>
  <p>{focusDiv}</p>
  <Parent setFocusDiv={setFocusDiv} />
  </>
  )
}

Parent Code:-

const Parent=()=>
{
  return (
  <>
  <h1>Parent</h1>
  <Child setFocusDiv={props.setFocusDiv} />
  </>
  )
}

Child Code:-

const Child=()=>
{

  function focus_fun(e) {
    if(e.target.id == "textID"){
        props.setFocusDiv(true);
      }
  }


  return (
  <>
  <h1>Child</h1>
  <input type="text" id="textID" onFocus={focus_fun} />
  </>
  )
}

Thanks for your efforts!

CodePudding user response:

You should also receive props in your Child and Parent

const Child=(props)=>
{

  function focus_fun(e) {
    if(e.target.id == "textID"){
        props.setFocusDiv(true);
      }
  }


  return (
  <>
  <h1>Child</h1>
  <input type="text" id="textID" onFocus={focus_fun} />
  </>
  )
}

Same for Parent

CodePudding user response:

Mehod #1

(not extensible very much and need to pass props around)

You need to define props input for your components pass the props from grandparent to child and also convert the boolean to a string otherwise it won't render the value:

const GrandParent = () => {
  const [focusDiv, setFocusDiv] = React.useState(false);
  return (
    <React.Fragment>
      <h1>GrandParent</h1>
      <p>{focusDiv.toString()}</p>
      <Parent setFocusDiv={setFocusDiv} />
    </React.Fragment>
  );
};

const Parent = (props) => {
  return (
    <React.Fragment>
      <h1>Parent</h1>
      <Child setFocusDiv={props.setFocusDiv} />
    </React.Fragment>
  );
};

const Child = (props) => {
  function focus_fun(e) {
    if (e.target.id == "textID") {
      props.setFocusDiv(true);
    }
  }

  return (
    <React.Fragment>
      <h1>Child</h1>
      <input type="text" id="textID" onFocus={focus_fun} />
    </React.Fragment>
  );
};

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

Mehod #2

Use CreateContext and useContext hooks to pass the state and setter methods directly to any child in the tree without using props:

const FocusContext = React.createContext();

const GrandParent = () => {
  const [focusDiv, setFocusDiv] = React.useState(false);
  return (
    <React.Fragment>
      <h1>GrandParent</h1>
      <p>{focusDiv.toString()}</p>
      <FocusContext.Provider value={{ focusDiv, setFocusDiv }}>
        <Parent />
      </FocusContext.Provider>
    </React.Fragment>
  );
};

const Parent = () => {
  return (
    <React.Fragment>
      <h1>Parent</h1>
      <Child />
    </React.Fragment>
  );
};

const Child = () => {
  const focus = React.useContext(FocusContext);

  function focus_fun(e) {
    if (e.target.id == "textID") {
      focus.setFocusDiv(true);
    }
  }

  return (
    <React.Fragment>
      <h1>Child</h1>
      <input type="text" id="textID" onFocus={focus_fun} />
    </React.Fragment>
  );
};

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

  • Related