【问题标题】:Input loses focus when typing输入时输入失去焦点
【发布时间】:2017-09-17 19:52:04
【问题描述】:

我在使用输入时遇到问题...我有两个输入:一个有自动对焦,另一个没有。但是,当我输入第二个输入时,它会失去焦点,焦点会返回到第一个输入。

我读过 React 在我输入内容时会重新渲染我的组件。我尝试放置一个关键道具等,但没有任何效果。

在我的表单(一个名为 Signup 的组件)中,我有以下内容:

import React from 'react'
import Input from '../../components/Input'
import styles from './styles.scss'

class Signup extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      name: '',
      email: '',
    }
  }

  onSignup (e, userData) {
    e.preventDefault()
    this.props.onSignup(userData)
  }

  render () {
    return (
      <main className={styles.wrapper}>
        <div className={styles.formSide}>
          <h1>SIGNUP</h1>

          <Input
            id="name"
            label="Name"
            onChange={e => this.setState({ name: e.target.value })}
            autofocus={true}
          />
          <Input
            id="email"
            label="E-mail"
            onChange={e => this.setState({ email: e.target.value })}
          />
        </div>
      </main>
    )
  }
}

Signup.propTypes = {
  onSignup: React.PropTypes.func.isRequired
}

export default Signup

我的组件输入有这个代码:

import React, { PropTypes } from 'react'
import MaskedInput from 'react-maskedinput'
import styles from './styles.scss'

function Input (props) {
  let iconComp

  if (props.icon) {
    iconComp = (<img src={props.icon} alt="Icon" />)
  }

  let input = ''

  if (props.type === 'date') {
    input = (
      <MaskedInput
        ref={inp => inp && props.autofocus && inp.focus()}
        onChange={props.onChange}
        mask="11/11/1111"
        placeholder={props.placeholder}
        className={styles.input}
      />
    )
  } else {
    input = (
      <input
        ref={inp => inp && props.autofocus && inp.focus()}
        onChange={props.onChange}
        id={props.id}
        placeholder={props.placeholder}
        type={props.type}
        className={styles.input}
      />
    )
  }

  return (
    <div className={styles.wrapper}>
      <label htmlFor={props.id} className={styles.label}>{props.label}</label>
      <br />
      {input}
      {props.error &&
        <span className={styles.error}>
          {props.errorMessage}
        </span>
      }
      {iconComp}
    </div>
  )
}

Input.propTypes = {
  id: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  icon: PropTypes.string,
  placeholder: PropTypes.string,
  type: PropTypes.string,
  autofocus: PropTypes.bool,
  onChange: PropTypes.func.isRequired,
  error: PropTypes.bool,
  errorMessage: PropTypes.string
}

Input.defaultProps = {
  icon: '',
  placeholder: '',
  type: 'text',
  autofocus: false,
  error: false,
  errorMessage: ''
}

export default Input

我该如何解决这个问题?

【问题讨论】:

  • 你能把它放在fiddle或plunker吗?
  • 如果你做一个演示,我想我有一个解决方案,但我无法测试它。
  • 谢谢,我有一个简单的解决方案。

标签: javascript reactjs


【解决方案1】:

所以一个简单的解决方案是增强您的 SignUp 组件,使其具有另一个名为 nameAutoFocus 的属性并将其初始化为 true。使用此属性设置自动对焦布尔值。然后添加方法 componentDidMount 并在里面设置 nameAutoFocus 为 false。

    class Signup extends React.Component {
      constructor (props) {
        super(props)
        this.state = {
          name: '',
          email: '',
        }

        this.nameAutoFocus = true; //new
      }

      onSignup (e, userData) {
        e.preventDefault()
        this.props.onSignup(userData)
      }

       //new
      componentDidMount() {
        this.nameAutoFocus = false;
      }

      render () {
        return (
          <main>
            <div>
              <h1>SIGNUP</h1>

              <Input
                id="name"
                label="Name"
                onChange={e => this.setState({ name: e.target.value })}
                autofocus={this.nameAutoFocus}
              />
              <Input
                id="email"
                label="E-mail"
                onChange={e => this.setState({ email: e.target.value })}
              />
            </div>
          </main>
        )
      }
    }

这是可行的,因为 nameAutoFocus 的初始值被传递给输入,使其获得焦点,然后 componentDidMount 将运行并将其设置为 false,因此下次状态更改时,它不会将 autofocus 属性设置为 true。这实质上是在最初渲染时只给它一次焦点。

codepen:http://codepen.io/floor_/pen/PmNRKV?editors=0011 不要忘记点击运行。

【讨论】:

    【解决方案2】:

    问题是每次渲染输入时,都会为ref 创建并调用新的线箭头函数。所以它每次都执行inp.focus()。避免这种情况的一种方法是使用类组件并将ref 回调方法定义为类函数。

    class Input extends React.Component {
    
      refCallback(inp){
        if(this.props.autofocus) inp.focus();
      }
    
      render(){
        let input = ''
    
        if (this.props.type === 'date') {
          input = (
            <MaskedInput
              ref={this.refCallback}
              onChange={this.props.onChange}
              mask="11/11/1111"
              placeholder={this.props.placeholder}
            />
          )
        } else {
          input = (
            <input
              ref={this.refCallback}
              onChange={this.props.onChange}
              id={this.props.id}
              placeholder={this.props.placeholder}
              type={this.props.type}
            />
          )
        }
    
        return (
          <div>
            <label htmlFor={this.props.id}>{this.props.label}</label>
            <br />
            {input}
          </div>
        )
      }
    }
    
    export default Input
    

    更新代码笔:http://codepen.io/anon/pen/jmqxWy

    (我之前的代码有一些问题,因为我无法测试它。但现在我已经更新了代码并且它可以工作了)

    【讨论】:

    • 很抱歉我的最后一条评论,但它奏效了!我会做一个演示,@floor
    • 我之前的代码有一些问题,因为我无法测试它。但是现在我已经更新了代码并且它可以工作了。我还包括了更新的 codepen。
    • @TharakaWijebandara 这个解决方案对我不起作用,在代码笔中也不起作用。
    • @floor 我很惊讶。这对我很有效。 drive.google.com/file/d/0Bzmd_IKe3Y-oNHFBYUxWM1FkdGs/…看看leonero怎么说。
    • 这个解决方案对我有用 :D 但@floor 的解决方案有点简单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 2021-12-14
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 2020-04-30
    相关资源
    最近更新 更多