输入时输入失去焦点

时间:2017-04-21 00:37:44

标签: javascript reactjs

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

我已经读过,当我输入内容时,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

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

所以一个简单的解决方案是增强你的SignUp组件以获得另一个名为nameAutoFocus的属性并将其初始化为true。使用此属性设置自动对焦布尔值。然后将方法componentDidMount和set 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 不要忘记点击运行。

答案 1 :(得分:0)

问题是每次渲染输入时,都会为const path = require('path'); const webpack = require('webpack'); const spawn = require('child_process').spawn; const HtmlWebpackPlugin = require('html-webpack-plugin'); const compiler = webpack({ // add your webpack configuration here entry: './app.js', output: { path: path.resolve(__dirname, 'dist'), filename: "bundle.js" }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['env', 'es2015', 'stage-2'] } } } ] }, /*plugins: [ new HtmlWebpackPlugin({ title: 'Project Demo', hash: true, template: './views/index.ejs' // Load a custom template (ejs by default see the FAQ for details) }) ],*/ node: { __dirname: false }, target: 'node' }); const watchConfig = { // compiler watch configuration // see https://webpack.js.org/configuration/watch/ aggregateTimeout: 300, poll: 1000 }; let serverControl; compiler.watch(watchConfig, (err, stats) => { if (err) { console.error(err.stack || err); if (err.details) { console.error(err.details); } return; } const info = stats.toJson(); if (stats.hasErrors()) { info.errors.forEach(message => console.log(message)); return; } if (stats.hasWarnings()) { info.warnings.forEach(message => console.log(message)); } if (serverControl) { serverControl.kill(); } // change filename to the relative path to the bundle created by webpack, if necessary(choose what to run) serverControl = spawn('node', [path.resolve(__dirname, 'dist/bundle.js')]); serverControl.stdout.on('data', data => console.log(data.toString())); serverControl.stderr.on('data', data => console.error(data.toString())); }); 创建新的线箭头函数并调用它。所以每次都执行ref。避免这种情况的一种方法是使用类组件并将inp.focus()回调方法定义为类函数。

ref

更新了codepen:http://codepen.io/anon/pen/jmqxWy

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