在 React-Hooks UseRef 我无法获得新的状态值

Posted

技术标签:

【中文标题】在 React-Hooks UseRef 我无法获得新的状态值【英文标题】:In React-Hooks UseRef i cant get the new state value 【发布时间】:2019-07-07 00:12:41 【问题描述】:

我正在尝试使用 react-hooks 使用 useref,但是当我调用 setAccountVal 方法时,虽然当我提醒该值时孩子的状态发生了变化,但它仍然是“Ege”。你对这个案子有什么想法吗?

    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;

当我调用普通方法时,我可以看到我想要什么。但问题是我可以在 acc 状态上看到新的状态值,但是当我从父级获取它时,它显示的是旧的(实际上是初始状态 val ("Ege"))状态值。

编辑:其实我想要做的是下面

//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.

好的!我找到了解决方案。现在,当我将 ref 变量与 getter setter 一起使用时,我还可以使用 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

详细演示:

.

【问题讨论】:

【参考方案1】:

这是因为您使用 useImperativeHandle 时没有设置任何输入,所以函数永远不会更新。只需添加 acc 作为输入,它就会起作用:

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

  setAccountVal(val: string) 
    setAcc(val);

  ,
  acc
), [acc]);

【讨论】:

嘿@anxo,谢谢!!,如何直接访问“acc”。我如何设置它的值?因为我可以得到它的值,但是当我设置它时它不会改变。 这取决于具体情况,但我的第一选择是将状态放在父级而不是子级上,并将其作为道具传递(包括设置器,如果需要),删除需要使用ImperativeHandle。如果这不是一个选项,我会选择 refs:它们是可变的,允许所有方法访问当前值而不会出现传播问题。如果您需要更多量身定制的建议,请随时提出新的具体问题。 快速浏览后,我会选择父级的状态。 React 基于单向数据流的概念,因此状态应该在所有需要它的位的共同祖先上,并且它会被传递下去。见reactjs.org/docs/state-and-lifecycle.html#the-data-flows-down。如果孩子需要改变它,只需让它从父母那里收到一个带有功能的道具。 非常感谢您的帮助。但实际上我需要直接到达裁判的状态。 useImperativeHandle 支持这个还是我应该直接使用 ref 而不使用 useImperativeHandle ?而且我不想提供所有组件内容。我需要一种可以直接与变量一起使用的 useImperativeHandle

以上是关于在 React-Hooks UseRef 我无法获得新的状态值的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:无法读取 React-hooks 中未定义的属性“toLowerCase”

在调用 useRef 当前对象的焦点时无法读取未定义的属性(读取“焦点”)

使用 useeffect 和 useref TypeError 时出错:无法读取 null 的属性“getBoundingClientRect”

类组件中的 UseRef。画布未定义

未处理的拒绝(TypeError):在 React 中使用 useRef 时无法读取未定义的属性(读取“值”)

React useRef 设置 DOM 节点的宽度