reactjs React Hooks -当输入1个字符时,输入失去焦点

2guxujil  于 2023-05-22  发布在  React
关注(0)|答案(5)|浏览(207)

我正在玩React Hooks -重写表单以使用钩子概念。一切都按预期工作,除了一旦我在输入中键入任何1个字符,输入就失去焦点。
我想这是一个问题,组件的外部不知道组件内部的变化,但我如何解决这个问题呢?
下面是useForm Hook:

import React, { useState } from "react";

export default function useForm(defaultState, label) {
  const [state, setState] = useState(defaultState);

  const FormComponent = () => (
    <form>
      <label htmlFor={label}>
        {label}
        <input
          type="text"
          id={label}
          value={state}
          placeholder={label}
          onChange={e => setState(e.target.value)}
        />
      </label>
    </form>
  );

  return [state, FormComponent, setState];
}

下面是使用Hook的组件:

function App() {
  const [formValue, Form, setFormValue] = useForm("San Francisco, CA", "Location");

  return (
    <Fragment>
      <h1>{formValue}</h1>
      <Form />
    </Fragment>
  );
}
oogrdqng

oogrdqng1#

虽然Kais的回答将解决症状,但它将留下未解决的原因。如果有多个输入,它也会失败--那么哪一个应该在重新渲染时自动聚焦?
当您在另一个函数的范围内定义组件(FormComponent)时,就会发生问题,该函数被称为App组件的每个渲染。这将在每次重新呈现App组件并调用useState时为您提供一个全新的FormComponent。这个新的组成部分,那么,没有重点。
就我个人而言,我会觉得再次返回组件从挂钩。我将定义一个FormComponent组件,并且只从useForm状态返回状态。
但是,最接近原始代码的工作示例可能是:

// useForm.js
import React, { useState } from "react";

// Define the FormComponent outside of your useForm hook
const FormComponent = ({ setState, state, label }) => (
  <form>
    <label htmlFor={label}>
      {label}
      <input
        type="text"
        id={label}
        value={state}
        placeholder={label}
        onChange={e => setState(e.target.value)}
      />
    </label>
  </form>
);

export default function useForm(defaultState, label) {
  const [state, setState] = useState(defaultState);

  return [
    state,
    <FormComponent state={state} setState={setState} label={label} />,
    setState
  ];
}
// App.js
import useForm from "./useForm";

export default function App() {
  const [formValue, Form] = useForm("San Francisco, CA", "Location");

  return (
    <>
      <h1>{formValue}</h1>
      {Form}
    </>
  );
}

Here's a sandbox

8yoxcaq7

8yoxcaq72#

在输入框中输入任何文本时。父组件也正在重新渲染。因此,您需要集中精力手动输入。为此,在input标记中使用autoFocus

<input
  type="text"
  id={label}
  value={state}
  placeholder={label}
  onChange={e => setState(e.target.value)}
  autoFocus
/>
93ze6v8z

93ze6v8z3#

上面的答案对我不起作用。对我有效的解决方案要简单得多,因此也不那么明显。

问题本质上,我随输入改变的值也被用于输入列表中的每个key

因此,当我更新key的值时,React会检测到它与最后一个键不同,并在其位置创建一个新的输入。作为一个新的输入,它不会专注于自己。
但是,通过使用autoFocus,它将自动关注新创建的输入。但是这个问题并没有得到解决,因为很明显,输入内容不断地经历着一个非焦点和焦点的循环。
这里有一个article demonstrating的问题。

修复

key更新为不可更改的值,以便React对列表项具有稳定的引用。在我的情况下,我只是更新到索引。这并不理想(React文档建议使用稳定ID),但在我的情况下,这是可以的,因为项目的顺序不会改变。

y53ybaqx

y53ybaqx4#

第一个解决方案实际上为我工作,最初包含文本字段的功能组件是主功能组件的一部分,我面临着同样的问题,但当我将文本字段组件提取到另一个页面并导入时,它工作正常。

<Paper >
      <div>
      <div style={{padding:'10px' ,display:'flex'}}  >       
      <inputstyle={{marginRight:'5px'}} value={val} onChange={(e)=>{setVal(e.target.value)}} />             
    </div>
    </div>
    </Paper>
disbfnqx

disbfnqx5#

我在使用样式化组件时遇到了这个问题,问题是样式化组件每次在输入上进行更改时都会更改类,而类更改会使组件重新呈现。
解决方案是像这样在函数组件之外声明样式化组件。

const FormButton = styled.button``

export default function Button(){
   return(   
      <FormButton>Log In</FormButton>        
)

相关问题