【问题标题】:In React ES6, why does the input field lose focus after typing a character?在 React ES6 中,为什么输入框在输入一个字符后会失去焦点?
【发布时间】:2017-07-23 05:13:15
【问题描述】:

在我下面的组件中,输入字段在输入字符后失去焦点。在使用 Chrome 的 Inspector 时,看起来整个表单正在重新呈现,而不仅仅是输入字段的 value 属性。

我从 eslint 和 Chrome Inspector 都没有收到任何错误。

提交表单本身的工作方式与实际输入字段一样,当它位于渲染的返回中或作为单独的组件导入时,而不是我在下面的编码方式。

为什么会这样?

主页组件

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actionPost from '../redux/action/actionPost';
import InputText from './form/InputText';
import InputSubmit from './form/InputSubmit';

class _PostSingle extends Component {
    constructor(props, context) {
        super(props, context);
        this.state = {
            post: {
                title: '',
            },
        };
        this.onChange = this.onChange.bind(this);
        this.onSubmit = this.onSubmit.bind(this);
    }
    onChange(event) {
        this.setState({
            post: {
                title: event.target.value,
            },
        });
    }
    onSubmit(event) {
        event.preventDefault();
        this.props.actions.postCreate(this.state.post);
        this.setState({
            post: {
                title: '',
            },
        });
    }
    render() {
        const onChange = this.onChange;
        const onSubmit = this.onSubmit;
        const valueTitle = this.state.post.title;
        const FormPostSingle = () => (
            <form onSubmit={onSubmit}>
                <InputText name="title" label="Title" placeholder="Enter a title" onChange={onChange} value={valueTitle} />
                <InputSubmit name="Save" />
            </form>
        );
        return (
            <main id="main" role="main">
                <div className="container-fluid">
                    <FormPostSingle />
                </div>
            </main>
        );
    }
}

_PostSingle.propTypes = {
    actions: PropTypes.objectOf(PropTypes.func).isRequired,
};

function mapStateToProps(state) {
    return {
        posts: state.posts,
    };
}

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators(actionPost, dispatch),
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(_PostSingle);

文本输入组件

import React, { PropTypes } from 'react';

const InputText = ({ name, label, placeholder, onChange, value, error }) => {
    const fieldClass = 'form-control input-lg';
    let wrapperClass = 'form-group';
    if (error && error.length > 0) {
        wrapperClass += ' has-error';
    }
    return (
        <div className={wrapperClass}>
            <label htmlFor={name} className="sr-only">{label}</label>
            <input type="text" id={name} name={name} placeholder={placeholder} onChange={onChange} value={value} className={fieldClass} />
            {error &&
                <div className="alert alert-danger">{error}</div>
            }
        </div>
    );
};

InputText.propTypes = {
    name: PropTypes.string.isRequired,
    label: PropTypes.string.isRequired,
    placeholder: PropTypes.string.isRequired,
    onChange: PropTypes.func.isRequired,
    value: PropTypes.string,
    error: PropTypes.string,
};

InputText.defaultProps = {
    value: null,
    error: null,
};

export default InputText;

提交按钮组件

import React, { PropTypes } from 'react';

const InputSubmit = ({ name }) => {
    const fieldClass = 'btn btn-primary btn-lg';
    return (
        <input type="submit" value={name} className={fieldClass} />
    );
};

InputSubmit.propTypes = {
    name: PropTypes.string,
};

InputSubmit.defaultProps = {
    name: 'Submit',
};

export default InputSubmit;

【问题讨论】:

    标签: reactjs text input ecmascript-6 focus


    【解决方案1】:

    当您输入一个字符时,您的表单会重新呈现,因为您有一个 onChange 方法,它会更改状态。每次状态更改都会导致表单重新呈现,这就是输入法失去焦点的原因。

    由于您使用的是 redux,因此最好的方法是将帖子标题值存储在 redux 对象中。此外,您可能想看看在您的表单中使用redux-form

    要获取不带re-rendering 的输入值,您需要使用refs

    【讨论】:

      【解决方案2】:

      发生了什么是这样的:

      当您的 onChange 事件触发时,回调会使用新的 title 值调用 setState,该值将作为道具传递给您的文本字段。此时,React 会渲染一个新组件,这就是您失去焦点的原因。

      我的第一个建议是提供您的组件键,尤其是表单和输入本身。 Keys 允许 React 通过渲染保留组件的身份。

      编辑:

      请参阅有关密钥的文档:https://reactjs.org/docs/lists-and-keys.html#keys

      【讨论】:

      • “提供您的组件密钥”是什么意思?你有任何文档的链接吗?
      • 正确解释原因,但关键建议不能解决问题。仅供那些不知道为什么解决方案对他们不起作用的人参考。
      • 对于谁可能有帮助,这也可能是由于在不需要它的地方有一个密钥。我在一个表的主体上有 key={Math.random()},然后它有动态行,这导致了这个错误。
      • 拥有不断变化的关键属性会导致组件总是被重新渲染,而不是被区分并仅重新渲染更改的部分。
      • @GavinMannion 这对我有用!你能更详细地解决它吗?为什么人们总是有这行代码?
      【解决方案3】:

      这是因为您在 render() 内部的函数中渲染表单。

      每次你的 state/prop 改变时,函数都会返回一个新的表单。它导致你失去焦点。

      尝试将函数内部的内容直接放入渲染中。

      <main id="main" role="main">
          <div className="container-fluid">
              <FormPostSingle />
          </div>
      </main>
      

      ===>

      <main id="main" role="main">
          <div className="container-fluid">
              <form onSubmit={onSubmit}>
                  <InputText name="title" label="Title" placeholder="Enter a title" onChange={onChange} value={valueTitle} />
                  <InputSubmit name="Save" />
              </form>
          </div>
      </main>
      

      【讨论】:

      • 不确定为什么在正确的情况下被否决。是匿名函数 FormPostSingle 导致了这个问题,因为它在 render 内部声明了一个带有新函数签名的新函数,每次渲染运行时都会创建一个新函数,这会导致 React 失去对它创建的元素的跟踪。
      • 所以我猜你是对的,但是你不能直接把元素放进去的原因很可能是因为你这样做的全部原因是为了得到不止一个的重用.如果你想要多个 FormPostSingle 组件,你会怎么做?
      • @Nateous 我的意思是。 “不要在渲染函数下创建表单函数”,如果你想复用一个表单组件,你应该创建一个单独的函数/组件文件并使用它。
      • 这个答案很有帮助,我把它变成了像{FormPostSingle(props)} 这样的函数调用,它立即起作用。我不知道你在说什么渲染函数,因为我使用钩子
      • 对于函数组件的人来说,这意味着不要在你的函数组件体内部定义组件......基本上每个组件都将位于模块的顶层(即使你有多个一个模块)....我在 func 中使用样式化组件定义遇到了这个问题。比较它看起来 像一个表达式,但当然它实际上是在(对我而言)奇怪的样式组件模板文字语法中调用一个函数。哎呀!
      【解决方案4】:

      我的问题是它在同一个文件的无状态组件中重新渲染。因此,一旦我摆脱了那个不必要的无状态组件并直接将代码放入,我就没有不必要的重新渲染

      render(){
         const NewSocialPost = () => 
             <div className='new-post'>
                 <input
                      onChange={(e) => this.setState({ newSocialPost: e.target.value })}
                      value={this.state.newSocialPost}/>
                 <button onClick={() => this._handleNewSocialPost()}>Submit</button>
            </div>
      
      return (
                  <div id='social-post-page'>
                      <div className='post-column'>
                          <div className='posts'>
                              <Stuff />
                          </div>
                          <NewSocialPost />
                      </div>
                      <MoreStuff />
                  </div>
      

      【讨论】:

      • 但是如果我们想要返回 200 个 组件,但又不想重复
        代码 200 次,你会怎么做?跨度>
      • @SterlingBourne 我相信您会想要更改父代码和映射代码的组件生命周期,所以{NewSocialPosts.map(SocialPost =&gt; &lt;NewSocialPost SocialPost={SocialPost} /&gt; )} 之类的事情
      【解决方案5】:

      我无权发表评论,那么它必须是一个答案。我有类似的问题,Alex Yan 的回答是正确的。

      也就是说我有那个功能

      const DisplaySearchArea =()=>{return (arrayOfSearchFieldNames.map((element, index)=>{return(<div key ={index} className = {inputFieldStyle}><input  placeholder= {arrayOfPlaceholders[index]} type="text" className='border-0'
      value={this.state[element]}
      onChange={e => {this.setState({ [element]: e.target.value }); console.log(e.target)}}
      onMouseEnter={e=>e.target.focus()}/></div>)}))}
      

      当呈现为&lt;DisplaySearchArea /&gt; 时,在 FF 和 Chrome 中的行为正常 当渲染为 {...} 时,两者都可以。这不是看起来那么“漂亮”的代码,但可以工作,我已经被告知有过度使用 lambdas 的倾向。

      【讨论】:

        【解决方案6】:

        我是 React 新手,一直遇到这个问题。

        这就是我要解决的问题:

        1. 首先将所有组件移动到组件文件夹中,然后将它们导入到您想要使用它们的位置
        2. 确保所有表单元素都获得nameid 属性
        3. 确保在您上树时所有组件都有一个唯一的key

        比我聪明的人可能会告诉我们为什么我们可以跳过第一步并将所有内容保持内联,但这只是帮助我组织代码。

        我认为真正的问题是 React 正在重新渲染所有内容(如前所述),有时重新渲染发生在没有 key 但需要一个的父组件上。

        我的问题是 ExpansionPanel 组件包装了我的自定义组件以进行表单输入。面板也需要key

        希望这对其他人有所帮助,这让我发疯了!

        【讨论】:

          【解决方案7】:

          谢谢,亚历克斯。这样我就解决了我的问题:

          constructor(props, context) {
              ...
              this.FormPostSingle = this.FormPostSingle.bind(this);
          }
          FormPostSingle() {
                  const onChange = this.onChange;
                  const onSubmit = this.onSubmit;
                  const valueTitle = this.state.post.title;
                  return (
                  <form onSubmit={onSubmit}>
                          <InputText name="title" label="Title" placeholder="Enter a title" onChange={onChange} value={valueTitle} />
                          <InputSubmit name="Save" />
                      </form>        );
          }
          render() {
              let FormPostSingle = this.FormPostSingle
              return...
          }
          

          【讨论】:

            【解决方案8】:

            这发生在我身上,虽然我设置了钥匙!

            原因如下:

            我正在使用来自文本字段的键。在同一个街区内;我有一个输入字段来更新同一文本字段的值。现在,由于组件键正在更改,因此 react 会重新渲染 UI。因此失去焦点。

            从中得到什么:

            不要使用不断变化的键。

            【讨论】:

              【解决方案9】:

              设置正确的 id,确保没有其他组件具有相同的 id,设置它唯一,它不应该在状态更新时改变,最常见的错误是在状态更新时用改变的值更新 id

              【讨论】:

                【解决方案10】:

                您必须为输入组件使用唯一键。

                <input key="random1" type="text" name="displayName" />
                

                key="random1" 不能随机生成。 例如,

                <div key={uuid()} className='scp-ren-row'>
                

                uuid() 将为每次重新渲染生成一组新的字符串。这将导致输入失去焦点。

                如果元素是在 .map() 函数中生成的,则使用索引作为键的一部分。

                {rens.map((ren,i)=>{
                    return(
                    <div key={`ren${i+1}`} className='scp-ren-row'>
                       {ren}{i}
                </div>)
                }
                

                这将解决问题。

                【讨论】:

                • 我使用uuid() 随机生成的密钥,但它不起作用,现在它可以...谢谢!
                • 谢谢,您的解决方案确实解决了我的问题。我是uuidv4来生成密钥的。
                【解决方案11】:

                遇到同样的问题并以快速简单的方式解决它:只需使用 {compName()} 而不是 &lt;compName /&gt; 调用组件

                例如,如果我们有:

                const foo = ({param1}) => {
                   // do your stuff
                   return (
                      <input type='text' onChange={onChange} value={value} />
                   );
                };
                
                const main = () => (
                   <foo param1={true} />
                );
                

                那么,我们只需要改变我们调用foo()组件的方式:

                const main = () => (
                   {foo({param1: true})}
                );
                

                【讨论】:

                • 多么奇怪和烦人,谢谢你的提示,这对我也有用!我以前使用 foo(),但将其更改为 。我不得不将其改回以使我的输入再次起作用。
                • 这个改变也对我有用。我想知道这是什么原因?
                • 请注意,如果您这样做并且您在foo 中有一个状态变量,您的父母将在每次 foo 的状态更改时重新渲染。
                • 非常感谢。这让我发疯,所以我不得不研究为什么会发生这种情况。如果您仍然感兴趣,这里有一个解释@Normal:link
                • Fcking 不断被创建为新的命名组件
                【解决方案12】:

                我遇到了这个问题,它是由react-bootstrap/Container 引起的,一旦我摆脱它,为每个表单元素添加一个唯一键,一切正常。

                【讨论】:

                  【解决方案13】:

                  我也遇到了这个问题,我的问题与使用另一个组件来包装文本区域有关。

                  // example with this problem
                  import React from 'react'
                  
                  const InputMulti = (props) => {
                    const Label = ({ label, children }) => (
                      <div>
                        <label>{label}</label>
                        { children }
                      </div>
                    )
                  
                    return (
                      <Label label={props.label}>
                        <textarea
                          value={props.value}
                          onChange={e => props.onChange(e.target.value)}
                        />
                      </Label>
                    )
                  }
                  
                  export default InputMulti
                  

                  当 state 发生变化时,react 会渲染 InputMulti 组件,每次都会重新定义 Label 组件,这意味着输出在结构上是相同的,但是由于 JS,函数会被认为是 !=

                  我的解决方案是将Label 组件移到InputMulti 组件之外,使其成为静态的。

                  // fixed example
                  import React from 'react'
                  
                  const Label = ({ label, children }) => (
                    <div>
                      <label>{label}</label>
                      { children }
                    </div>
                  )
                  
                  const InputMulti = (props) => {
                    return (
                      <Label label={props.label}>
                        <textarea
                          value={props.value}
                          onChange={e => props.onChange(e.target.value)}
                        />
                      </Label>
                    )
                  }
                  
                  export default InputMulti
                  

                  我注意到人们经常将本地使用的组件放在想要使用它的组件中。通常是为了利用函数作用域并获得对父组件 props 的访问权限。

                  const ParentComp = ({ children, scopedValue }) => {
                    const ScopedComp = () => (<div>{ scopedValue }</div>)
                    return <ScopedComp />
                  }
                  

                  我从未真正想过为什么需要这样做,因为您可以将 props 钻入内部函数并将其从父组件外部化。

                  这个问题是一个完美的例子,说明了为什么您应该始终将您的组件相互外部化,即使它们在一个模块中使用。此外,您始终可以使用智能文件夹结构来保持附近的东西。

                  src/
                    components/
                      ParentComp/
                        ParentComp.js
                        components/
                          ScopedComp.js
                  

                  【讨论】:

                  • 花了很长时间试图解决这个问题,认为你的答案无关紧要,然后意识到它和我的一样!!谢谢!!!!!!
                  【解决方案14】:

                  在我的情况下,我有一个孩子,

                    //in fact is a constant
                    const RenderOnDelete=()=>(
                    <>  .
                        .
                        <InputText/>
                        .
                        .
                    </>
                  )
                  
                  
                  //is a function that return a constant
                  const RenderOnRadioSelected=()=>{
                    
                    switch (selectedRadio) {
                      case RADIO_VAL_EXIST:
                             return <RenderOnExist/>
                      case RADIO_VAL_NEW:
                             return <RenderOnNew/>
                      case RADIO_VAL_DELETE:
                             return <RenderOnDelete/>
                      default:
                            return <div>Error</div>
                    }
                  }
                  

                  这在父级中

                  return(
                  <> 
                  .
                  <RenderOnRadioSelected/>
                  .
                  </>
                  )
                  

                  Y 解决了这个问题不调用组件,而是调用 function() 或常量,具体取决于具体情况。 . . .

                    //in fact is a constant
                    const RenderOnDelete=(
                    <>  .
                        .
                        <InputText/>
                        .
                        .
                    </>
                  )
                  
                  
                  //is a function that return a constant
                  const RenderOnRadioSelected=()=>{
                    
                    switch (selectedRadio) {
                      case RADIO_VAL_EXIST:
                             return {RenderOnExist}
                      case RADIO_VAL_NEW:
                             return {RenderOnNew}
                      case RADIO_VAL_DELETE:
                             return {RenderOnDelete}//Calling the constant
                      default:
                            return <div>Error</div>
                    }
                  }
                  

                  这在父级中

                  return(
                  <> 
                  .
                  {RenderOnRadioSelected()}//Calling the function but not as a component
                  .
                  </>
                  )
                  

                  【讨论】:

                  • 嗨,欢迎来到堆栈溢出!如果您遇到问题,请随时ask new questions
                  【解决方案15】:

                  对于那些在 React Native 上面临输入单个字符后文本输入失去焦点的问题。 尝试将您的 onChangeText 传递给您的 TextInput 组件。 例如:

                  const [value, setValue] = useState("")
                  const onChangeText = (text) => {
                        setValue(text)
                  }
                  return <TextInput value={value} onChangeText={onChangeText} />
                  

                  【讨论】:

                    【解决方案16】:

                    添加另一个答案:当我在另一个组件中返回一个高阶组件时,这发生在我身上。例如,而不是:

                    /* A function that makes a higher order component */
                    const makeMyAwesomeHocComponent = <P, >(Component: React.FC<P>) => {
                        const AwesomeComponent: React.FC<P & AwesomeProp> = (props) => {
                            const { awesomeThing, ...passThroughProps } = props;    
                    
                            return (
                                <strong>Look at: {awesomeThing}!</strong>
                                <Component {...passThroughProps} />
                            );
                    
                        }
                    
                        return AwesomeComponent;
                    }
                    
                    /* The form we want to render */
                    const MyForm: React.FC<{}> = (props) => {
                    
                        const MyAwesomeComponent: React.FC<TextInputProps & AwesomeProp> = 
                            makeMyAwesomeHocComponent(TextInput);
                    
                        return <MyAwesomeComponent awesomeThing={"cat"} onChange={() => { /* whatever */ }} />
                    }
                    
                    

                    将创建高阶组件的调用移出您正在渲染的内容。

                    const makeMyAwesomeHocComponent = <P, >(Component: React.FC<P>) => {
                        const AwesomeComponent: React.FC<P & AwesomeProp> = (props) => {
                            const { awesomeThing, ...passThroughProps } = props;    
                    
                            return (
                                <strong>Look at: {awesomeThing}!</strong>
                                <Component {...passThroughProps} />
                            );
                    
                        }
                    
                        return AwesomeComponent;
                    }
                    
                    /* We moved this declaration */
                    const MyAwesomeComponent: React.FC<TextInputProps & AwesomeProp> = 
                        makeMyAwesomeHocComponent(TextInput);
                    
                    /* The form we want to render */
                    const MyForm: React.FC<{}> = (props) => {
                        return <MyAwesomeComponent awesomeThing={"cat"} onChange={() => { /* whatever */ }} />
                    }
                    
                    

                    【讨论】:

                      【解决方案17】:

                      基本上创建一个 ref 并将其分配给输入元素

                      const inputRef = useRef(null); // Javascript
                      
                      const inputRef = useRef<HTMLInputElement>(null); // Typescript
                      
                      // In your Input Element use ref and add autofocus
                      
                      <input ref={inputRef} autoFocus={inputRef.current === document.activeElement} {...restProps} />
                      

                      这将使输入元素在键入时保持焦点。

                      【讨论】:

                        【解决方案18】:

                        通过添加

                        autoFocus="autoFocus"
                        

                        input为我工作

                        <input
                          type="text"
                          autoFocus="autoFocus"
                          value = {searchString}
                          onChange = {handleChange}
                        />
                        

                        【讨论】:

                        • 不会因为 react 重新渲染输入元素而失去焦点吗?这只是隐藏了实际问题。
                        • 如果我们在子组件中有多个输入,这将不起作用
                        • @SujayUN 你是指同时有多个auto focus的输入框吗?
                        • 不,会有多个输入字段,但需要关注相同的用户正在输入@flos
                        【解决方案19】:

                        这个问题的解决方案是使用 useCallback 来记忆函数,这意味着它缓存了给定一组输入参数的函数的返回值。

                        const InputForm = useCallback(({ label, lablevalue, placeholder, type, value,setValue }) => {
                          return (
                              <input
                                key={label}
                                type={type}
                                value={value}
                                onChange={(e) => setIpValue(e.target.value)}
                                 placeholder={placeholder}
                              />
                              );
                        },[]);
                        

                        希望它能解决你的问题

                        【讨论】:

                        • 遗憾的是,这在这种情况下不会有太大的不同。一方面,您忘记将依赖键添加到数组中,因此输入的值不会在输入时更新。其次,因为如果你添加了依赖键,那么值将会改变,因此尽管useCallback,组件将被重新渲染。
                        【解决方案20】:

                        问题是由useState() 函数引起的动态渲染(),因此您可以这样做。 在此代码中,您应该使用 onChange() 来获取新的更新数据,并使用 onMouseLeave() 来处理更新,但条件是更改数据以获得更好的性能

                        示例孩子

                                export default function Child(){
                                const [dataC,setDataC]=useState()
                                return(<Grid>
                                <TextField 
                                .
                                .
                                onChange={(r)=> setDataC(r.target.value) }
                                onMouseLeave={(e)=> {   
                                  if(dataC!=props.data) { // to avoid call handleupdate each time you leave the textfield
                                    props.handlechange(e.target.value)  // update partent.data 
                                  }
                                }
                                    
                                />
                                
                                </Grid>)
                            
                            }
                        

                        示例父级

                        export default function Parent(){
                        const [data,setData]=useState()
                        return(
                         <Grid>
                            <Child handlechange={handlechanges} data={data}/>
                         </Grid>)
                        }
                        

                        【讨论】:

                          【解决方案21】:

                          这是一个很好的问题,我也遇到了同样的问题,分为 3 个部分。

                          1. 随机生成的密钥。
                          2. 错误的事件类型。
                          3. 反应 JSX 属性错误。

                          键:当您使用随机键时,每次重新渲染都会导致 react 失去焦点 (key={Math.random()*36.4621596072})。

                          EventTypes: onChange 会导致每次击键时重新渲染,但这也可能导致问题。 onBlur 更好,因为它会在您在输入外部单击后更新。除非您想将输入“绑定”到屏幕上的某些内容(可视化构建器),否则输入应使用 onBlur 事件。

                          属性:JSX 不是 HTML 并且有它自己的属性(类名,...)。 最好在输入中使用 defaultValue={foo} 而不是使用值。

                          一旦我改变了这 3 件事,它就很有效。下面的例子。

                          家长:

                          const [near, setNear] = useState( "" );
                          const [location, setLocation] = useState( "" );
                           <ExperienceFormWhere 
                                  slug={slug} 
                                  questionWhere={question_where} 
                                  setLocation={handleChangeSetLocation} 
                                  locationState={location} 
                                  setNear={setNear} 
                                  nearState={near} 
                                  key={36.4621596072}/>
                          

                          孩子:

                          <input 
                          defaultValue={locationState} 
                          className={slug+"_question_where_select search_a_location"} 
                          onBlur={event => setLocation(event.target.value)}/>
                          

                          【讨论】:

                            【解决方案22】:

                            我遇到了同样的问题,只要我输入任何字符,它就会失去焦点。添加自动对焦道具帮助我解决了这个问题。

                            TypeScript Code Snippet

                            【讨论】:

                              【解决方案23】:

                              如果您碰巧正在为应用的设计系统开发原子组件,您可能会遇到这个问题。

                              考虑以下Input 组件:

                              export const Input = forwardRef(function Input(
                                props: InputProps,
                                ref: ForwardedRef<HTMLInputElement>,
                              ) {
                                const InputElement = () => (
                                  <input ref={ref} {...props} />
                                );
                              
                                if (props.icon) {
                                  return (
                                    <span className="relative">
                                      <span className="absolute inset-y-0 left-0 flex items-center pl-2">
                                        <label htmlFor={props.id} className="p-1 cursor-pointer">
                                          {icon}
                                        </label>
                                      </span>
                                      <InputElement />
                                    </span>
                                  );
                                } else {
                                  return <InputElement />;
                                }
                              });
                              

                              在条件渲染的两个分支中重用 input 元素似乎是一个简单的优化。然而,只要这个组件的父组件重新渲染,这个组件就会重新渲染,当 react 在树中看到 &lt;InputElement /&gt; 时,它也会渲染一个新的 &lt;input&gt; 元素,因此,现有的元素将失去焦点.

                              你的选择是

                              1. 使用useMemo 记忆组件
                              2. 复制一些代码并在条件渲染的两个分支中定义&lt;input&gt; 元素。在这种情况下,没关系,因为&lt;input&gt; 元素相对简单。更复杂的组件可能需要选项 1

                              所以你的代码就变成了:

                              export const Input = forwardRef(function Input(
                                props: InputProps,
                                ref: ForwardedRef<HTMLInputElement>,
                              ) {
                                if (props.icon) {
                                  return (
                                    <span className="relative">
                                      <span className="absolute inset-y-0 left-0 flex items-center pl-2">
                                        <label htmlFor={props.id} className="p-1 cursor-pointer">
                                          {icon}
                                        </label>
                                      </span>
                                      <input ref={ref} {...props} />
                                    </span>
                                  );
                                } else {
                                  return <input ref={ref} {...props} />;
                                }
                              });
                              

                              【讨论】:

                                猜你喜欢
                                相关资源
                                最近更新 更多
                                热门标签