Egomen
Egomen

Reputation: 93

In React-Hooks UseRef i cant get the new state value

I am trying useref with react-hooks but when i call the setAccountVal method , although the state of child changes when i alert the value it is still "Ege". Do you have any idea about this case ?

    import React, { useState, useRef, useImperativeHandle, useEffect, forwardRef } from "react";
interface A {
    name?: string;
}

const Child = forwardRef((props: A, ref) => {
    const [acc, setAcc] = useState("Ege");
    useImperativeHandle(ref, () => ({
        getAlert(value: string) {
            alert("getAlert from Child===>" + value);
        },

        setAccountVal(val: string) {
            setAcc(val);

        },
        acc
    }));

    useEffect(
        () => {
            debugger;
            setAcc(props.name || "dummy");
            console.log(acc + " --");
        },
        [props.name]
    );

const changeState = (e:React.FormEvent<HTMLInputElement>)=>{
    setAcc(e.currentTarget.value);
}


    return <input onChange={changeState}></input>;
})
function App() {
    let [name, setName] = useState("Nate");

    let nameRef = useRef<any>(null);

    const submitButton = () => {
        debugger;
        const comp = nameRef.current;
        comp.setAccountVal("Mahmut");
        comp.getAlert(comp.acc);
    };

    return (
        <div className="App">
            <p>{name}</p>
            <div>
                <button type="button" onClick={submitButton}>
                    Submit
        </button>
                <Child ref={nameRef} />
            </div>
        </div>
    );
}

export default App;

When i call a normal method , i can see what i want. But the problem is that i can see new state value on acc state but when i take it from parent it is displaying the old ( actually the initial state val ("Ege")) state value.

Edit : Actually what i want to do is below

//Child component with forwardRef
const [account, setAccount] = useState("defaultAccount");
const [branch, setBranch] = useState("defaultBranch");
const [person, setPerson] = useState("defaultPerson");

useImperativeHandle(ref, () => ({
    selectedAccount: account,
    selectedBranch: branch,
    selectedPerson: person
}));


//Parent component
const childComponentRef = useRef(null);
//Is it possible to change child component's state? Is it allowed?
childComponentRef.current.selectedAccount = "new account";
childComponentRef.current.selectedBranch = "new branch";
childComponentRef.current.selectedPerson = "new person";

alert(childComponentRef.current.selectedAccount);
alert(childComponentRef.current.selectedBranch);
alert(childComponentRef.current.selectedPerson);

//We can change these variables but child component does not rerender with new values.

Ok! I've found the solution. When i use the ref variables with getter setter now i can set also get the current values with useRef!!

//Child component with forwardRef
const [account, setAccount] = useState("defaultAccount");
const [branch, setBranch] = useState("defaultBranch");
const [person, setPerson] = useState("defaultPerson");

useImperativeHandle(ref, () => ({
    **get account(){
     return account;
    },
    set account(val : string){
    setAccount(val);
    },**
    selectedBranch: branch,
    selectedPerson: person
}));


//Parent component
const childComponentRef = useRef(null);
//Is it possible to change child component's state? Is it allowed?
childComponentRef.current.selectedAccount = "new account";
childComponentRef.current.selectedBranch = "new branch";
childComponentRef.current.selectedPerson = "new person";

alert(childComponentRef.current.selectedAccount);
alert(childComponentRef.current.selectedBranch);
alert(childComponentRef.current.selectedPerson);

//We can change these variables but child component does not rerender with new values

Detailed Demo :

Edit React-Ref with Hooks .

Upvotes: 2

Views: 8525

Answers (1)

Anxo
Anxo

Reputation: 475

It is because you're using useImperativeHandle without setting any inputs to it, so the functions never get updated. Just add acc as an input, and it will work:

useImperativeHandle(ref, () => ({
  getAlert(value: string) {
    alert("getAlert from Child===>" + value);
  },

  setAccountVal(val: string) {
    setAcc(val);

  },
  acc
}), [acc]);

Upvotes: 4

Related Questions