我正在尝试使用一个钩子来创建一个文本框,该文本框将值状态作为钩子的一部分提供。
但是,我并不是很成功,因为每当我尝试键入时,文本框都会失去焦点。
如果我展示自己在做什么,这可能更有意义。
请参阅此Codepen进行快速演示。 (https://codepen.io/david_yau/pen/RwWVoKz?editors=1111)
详细说明
// My first attempt
// App.jsx, the App
const App = () => {
const [text, TextBox] = useTextBox();
return (
<div>
<TextBox />
<p>
text: {text}
</p>
</div>
)
}
// useTextBox.jsx
const useTextBox = () => {
const [text, setText] = React.useState("");
const onChange = (event) => {
setText(event.target.value);
}
const TextBox = () => {
return (
<input type="text" value={text} onChange={onChange} />
)
};
return [text, TextBox];
}
这种方式行不通,因为每次我在文本框中键入内容时,焦点都会丢失。
但是,如果我将实现更改为以下内容,它将起作用。
此实现之间的区别在于,上述实现是使用<TextBox />
渲染一个新的TextBox。最底层的是使用渲染的文本框,例如{TextBox}
。
// App.jsx
const App = () => {
const [text, TextBox] = useTextBoxOne();
return (
<div>
<h1> This one work </h1>
{TextBox}
<p>
text: {text}
</p>
</div>
)
}
// useTextBox.jsx
const useTextBox = () => {
const [text, setText] = React.useState("");
const onChange = (event) => {
setText(event.target.value);
}
const TextBox = (
<input type="text" value={text} onChange={onChange} />
);
return [text, TextBox];
}
如果有帮助的话,我从“ {H3}}课程的“ Custom Hook”课程中得到了这个想法。
由于这是一个很长的帖子,所以只需重申一下这个问题。我想知道为什么第一种方法不起作用,因为它不断失去关注,而第二种方法却失去了作用。
答案 0 :(得分:2)
因为const TextBox = () => <input />
将在每次调用useTextBoxTwo()
时创建一个不同的React组件,而const TextBox = <input />
只是一个React元素,呈现在同一Component中(在App
中)
在当前实现中,当组件内部的元素发生更改时,ReactDOM会检查它是否具有相同的元素名称(例如“ input”)并且没有不同的key
-为true时,它将重新使用相同的DOM元素,例如以下2个React元素将重用相同的DOM元素(不会失去焦点):
{condition ? <input value="a" /> : <input value="b" />}
但是2种不同的React组件将触发旧组件的卸载,将其从DOM中删除,然后安装新组件,从而创建新的DOM元素(=>失去焦点)。
因此,请勿在自定义钩子内创建组件,而应创建使用钩子的自定义组件。