【发布时间】:2019-11-02 06:54:17
【问题描述】:
我想知道如何在函数中获取更新后的labelRef,即inputBlur()
import React, { useState, useRef, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [inputValue, setInputValue] = useState("Type...");
const [labelWidth, setLabelWidth] = useState();
const labelRef = useRef();
const inputChange = e => {
setInputValue(e.target.value);
setLabelWidth(labelRef.current.offsetWidth);
};
const inputBlur = e => {
const trimmed = e.target.value.trim();
if (trimmed) {
setInputValue(trimmed);
} else {
setInputValue("Type...");
}
setLabelWidth(labelRef.current.offsetWidth);
};
useEffect(() => {
setLabelWidth(labelRef.current.offsetWidth);
}, []);
return (
<div className="App">
<p>Type below to see if input and div is the same width</p>
<div ref={labelRef}>{inputValue}</div>
<br />
<input
value={inputValue}
onChange={e => inputChange(e)}
onBlur={e => inputBlur(e)}
style={{ width: `${labelWidth}px` }}
/>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
为了稍微解释一下这个例子,有一个输入字段通过用相同的文本填充div 来改变其宽度。目前,当输入字段为空后跟onblur 事件时,它无法正常工作。输入字段应使用默认值useState 填充,"Type...",但输入字段宽度为 0。
我看到的问题是在inputBlur函数中,在触发setInputValue之后,labelRef.current.offsetWidth这行仍然反映了旧元素,因为它还没有重新渲染那个元素。
这里是这个例子的link to the codesandbox 来尝试复制这个问题。
我的问题来自于对 react hook 的流程缺乏了解。我需要在useState用默认值更新元素后捕获事件,然后计算宽度。
注意:我不希望输入在仍处于焦点时自动使用默认值填充空输入字段。必须在 onBlur() 事件中填写。
【问题讨论】:
-
为什么你需要
setLabelWidth而不是仅仅使用引用style={{ width: `${labelRef.current.offsetWidth}px` }}? -
我认为
labelRef最初可以在 componentDidMount 中访问,就像在 useEffect 中一样。虽然我最初可以像您提到的那样得到labelRef,但labelRef.current返回未定义。我的评价对吗?你能让它以这种方式工作吗? -
对,它需要是
labelRef.current?.offsetWidth或一个很好的旧labelRef.current && labelRef.current.offsetWidth...
标签: reactjs input dom-events react-hooks