反应,使用Hooks创建组件

问题描述 投票:0回答:1

我正在尝试使用一个钩子来创建一个文本框,该文本框将值状态作为钩子的一部分提供。

但是,我并不是很成功,因为每当我尝试键入时,文本框都会失去焦点。

如果我展示自己在做什么,这可能更有意义。

请参阅此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];
}

如果有帮助,我从本课程中得到了这个主意:https://frontendmasters.com/courses/complete-react-v5/,在“自定义挂钩”会议上。

仅重申一个问题,因为这是一篇很长的文章。我想知道为什么第一种方法不起作用,因为它会不断失去关注,而第二种方法却不能。

reactjs react-hooks
1个回答
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元素(=>失去焦点)。


因此,请勿在自定义钩子内创建组件,而应创建使用钩子的自定义组件。


0
投票

因为每次调用const TextBox = () => <input />useTextBoxTwo()都会创建一个不同的React组件,而const TextBox = <input />只是一个React元素,呈现在同一Component(在App中)。

© www.soinside.com 2019 - 2024. All rights reserved.