我不知道为什么粘贴到我的电子邮件后,它会在文本框中复制它。
screencast of the problem
看来 当我粘贴时,它会正确触发 handleEmailPaste
但我也注意到 handleEmailPaste
也会被触发 过去所以不知道为什么。我想粘贴是一种变化,所以在文本中粘贴会触发这两个功能可能是有道理的。 如果我注释掉 handleEmailInput
中的代码, 并粘贴一个值,它不会复制它。
我想我不知道处理这个问题的正确方法。在我看来,我确实需要两个单独的处理程序。请注意,我正在使用引导控件,并且在其上设置了 onChange 和 onPaste:
<FormControl
bsSize="small"
className="ft-username"
componentClass="input"
onPaste={this.props.handleEmailPaste}
onChange={this.props.handleEmailInput}
placeholder="Enter email"
style={{ width: 300}}
type="email"
value={this.props.email}
/>
登录容器
import { connect } from 'react-redux'
import React, { Component } from 'react'
const zxcvbn = require('zxcvbn'),
_ = require('lodash')
import * as AsyncActions from '../actions/Auth/AuthAsyncActions'
import Login from '../components/Login/Login'
class LoginContainer extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
password: '',
errorMessage: '',
emailValidationState: null,
formIsValid: false,
formValidationState: null,
passwordValidationState: null,
passwordIsValid: null
}
this.handleEmailPaste = this.handleEmailPaste.bind(this)
this.handleEmailInput = this.handleEmailInput.bind(this)
this.handlePasswordInput = this.handlePasswordInput.bind(this)
this.handleLoginPressed = this.handleLoginPressed.bind(this)
this.resetFields = this.resetFields.bind(this)
this.validateForm = this.validateForm.bind(this)
this.validateEmail = this.validateEmail.bind(this)
this.validatePassword = this.validatePassword.bind(this)
}
handlePasswordInput(e) {
const password = e.target.value
this.setState({ password: password})
this.validatePassword()
}
handleEmailPaste(e){
console.log(`handleEmailPaste: ${e.clipboardData.getData('Text')}`)
const value = e.clipboardData.getData('Text')
this.setState({ email: value })
this.validateEmail(value)
}
handleEmailInput(e) {
this.setState({ email: e.target.value })
this.validateEmail()
}
async handleLoginPressed(e) {
e.preventDefault()
this.validateForm()
await this.props.authenticate(this.state.email, this.state.password)
if(this.props.isAuthenticated) {
this.props.history.push('/dashboard')
return
}
if(!this.props.isAuthenticated){
this.setState({
formValidationState: 'error',
errorMessage: this.state.formIsValid &&
'Your password and/or email is not associated with an active user'
})
if(this.state.email && this.state.password){this.resetFields()}
}
}
validateForm(){
this.validateEmail()
this.validatePassword()
this.setState({
formIsValid: (this.state.emailValidationState === 'success'
&& this.state.passwordValidationState === 'success')})
}
validatePassword(){
const password = zxcvbn(this.state.password)
if(password.score >=0){
this.setState({
passwordValidationState: 'error',
passwordHelpText: password.feedback.suggestions})
return
}
this.setState({
passwordValidationState: 'success',
passwordHelpText: null })
}
validateEmail(value){
if((!_.isEmpty(value)) || !_.isEmpty(this.state.email)) {
this.setState({
emailValidationState: 'success',
emailError: ''
})
return
}
this.setState({
emailValidationState: 'error',
emailError: 'please enter an email address'
})
}
resetFields(){
this.setState({
email: '',
emailError: '',
emailValidationState: null,
password: '',
passwordHelpText: '',
passwordValidationState: null })
}
render(){
return(
<div>
<Login
email={this.state.email}
emailError={this.state.emailError}
emailValidationState={this.state.emailValidationState}
errorMessage={this.state.errorMessage}
formValidationState={this.state.formValidationState}
handleEmailInput={this.handleEmailInput}
handleEmailPaste={this.handleEmailPaste}
handlePasswordInput={this.handlePasswordInput}
login={this.handleLoginPressed}
password={this.state.password}
passwordHelpText={this.state.passwordHelpText}
passwordValidationState={this.state.passwordValidationState}
/>
</div>
)
}
}
const mapStateToProps = state => ({
isAuthenticating: state.auth.isAuthenticating,
isAuthenticated: state.auth.isAuthenticated,
token: state.auth.token
})
export const mapDispatchToProps = {
authenticate: AsyncActions.authenticate
}
export { Login }
export default connect(mapStateToProps, mapDispatchToProps)(LoginContainer)
登录
import React, {Component} from 'react'
import LoginForm from './LoginForm'
export default class Login extends Component {
render(){
return (
<div>
<LoginForm
email={this.props.email}
emailError={this.props.emailError}
emailValidationState={this.props.emailValidationState}
errorMessage={this.props.errorMessage}
formValidationState={this.props.formValidationState}
handleEmailInput={this.props.handleEmailInput}
handleEmailPaste={this.props.handleEmailPaste}
handlePasswordInput={this.props.handlePasswordInput}
login={this.props.login}
password={this.props.password}
passwordHelpText={this.props.passwordHelpText}
passwordValidationState={this.props.passwordValidationState}
/>
</div>
)
}
}
登录表格
import React, { Component } from 'react'
import {
Button,
ControlLabel,
HelpBlock,
FormControl,
FormGroup,
PageHeader } from 'react-bootstrap'
export default class LoginForm extends Component {
render(){
return (
<div className='ft-login-form'>
<PageHeader className='ft-header'><small>Login</small></PageHeader>
<form onSubmit={this.props.login}>
<FormGroup validationState={this.props.formValidationState}>
<ControlLabel className="ft-form-error-message">{this.props.errorMessage}</ControlLabel>
</FormGroup>
<FormGroup controlId="formBasicText" validationState={this.props.emailValidationState}>
<ControlLabel>Email</ControlLabel>
<FormControl
bsSize="small"
className="ft-username"
componentClass="input"
onPaste={this.props.handleEmailPaste}
onChange={this.props.handleEmailInput}
placeholder="Enter email"
style={{ width: 300}}
type="email"
value={this.props.email}
/>
<HelpBlock className="ft-email-error">{this.props.emailError}</HelpBlock>
</FormGroup>
<FormGroup validationState={this.props.passwordValidationState}>
<ControlLabel>Password</ControlLabel>
<FormControl
bsSize="small"
className="ft-password"
componentClass="input"
onPaste={this.props.handleEmailPaste}
onChange={this.props.handlePasswordInput}
placeholder="Enter password"
style={{ width: 300}}
type="password"
value={this.props.password}
/>
<HelpBlock className="ft-password-help-text">{this.props.passwordHelpText}</HelpBlock>
</FormGroup>
<Button
className='ft-login-button'
type='submit'
>Login</Button>
</form>
</div>)
}
}
更新
所以我添加了这个,这解决了这个问题:
handleEmailInput(e) {
if(!this.state.email) {
this.setState({email: e.target.value})
}
this.validateEmail()
}
基本上在这里我是说嘿,如果有人最初粘贴它,它会命中
handleEmailPaste
它为电子邮件设置了状态,所以如果是这种情况,(我知道 handleEmailInput 也将由该粘贴/更改触发),那么如果 handleEmailPaste 已经设置它,我不想再次设置状态。相反,如果用户键入一个值而不是粘贴它,那么这个 if 语句将是 bypassed
因此handleEmailInput would setState in that case
.但我对电子邮件输入的整个处理对我来说感觉很糟糕。如果您认为这是一个 hack,并且对重构此代码有更好的想法,请告诉我。
更新 #2
废话,我注意到我没有得到重复但现在我无法在电子邮件框中输入新值,它不会让我,它只是坐在那里填充电子邮件但我无法修改它。
更新#3
(咆哮:为什么StackOverflow不让帖子正文文本区域的高度变大,当我滚动时我几乎看不到我在做什么)
所以真的我的问题不再是它复制我粘贴的文本的问题。我回到第一方,我原来的问题是我可以粘贴一些东西,但它使输入无效,我不知道为什么。我想我应该更新这篇文章的标题,但是哦。
无论如何,我只使用了
onChange
并摆脱了onPaste。没有更多的重复发生所以问题是:当您第一次将值粘贴到电子邮件文本框时的初始行为。当您第一次粘贴一个值时,我看到的行为(下面是没有 onPaste 的更新代码):
handleEmailInput()
方法。 handleEmailInput
来电setState({email: e.target.value})
所以你会认为这是为 this.state.email handleEmailInput
来电validateEmail()
紧接着,validateEmail
,它会检查 this.state.email
它是 还是 ""
由于某些原因。因此它最终到达第二个 setState 将其设置为无效 . 不是吗?第一次通话至
this.setState({email: e.target.value })
设置 this.state.email
到粘贴的电子邮件??我知道当我在那行设置断点时,e.target.value
有我粘贴的电子邮件,但是 之后 this.setState({email: e.target.value })
已完成调用,由于某种原因,在 validateEmail() 中它仍然得到 ""
对于 this.state.email,我不明白为什么。也许这是 React 及其生命周期的基础?或其他一些我还不知道的基本原理……不确定。登录容器
(我已经完全删除了 onPaste 逻辑)
import { connect } from 'react-redux'
import React, { Component } from 'react'
const zxcvbn = require('zxcvbn'),
_ = require('lodash')
import * as AsyncActions from '../actions/Auth/AuthAsyncActions'
import Login from '../components/Login/Login'
class LoginContainer extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
password: '',
errorMessage: '',
emailValidationState: null,
formIsValid: false,
formValidationState: null,
passwordValidationState: null,
passwordIsValid: null
}
this.handleEmailInput = this.handleEmailInput.bind(this)
this.handlePasswordInput = this.handlePasswordInput.bind(this)
this.handleLoginPressed = this.handleLoginPressed.bind(this)
this.resetFields = this.resetFields.bind(this)
this.validateForm = this.validateForm.bind(this)
this.validateEmail = this.validateEmail.bind(this)
this.validatePassword = this.validatePassword.bind(this)
}
handlePasswordInput(e) {
const password = e.target.value
this.setState({ password: password})
this.validatePassword()
}
handleEmailInput(e) {
this.setState({email: e.target.value })
this.validateEmail()
}
async handleLoginPressed(e) {
e.preventDefault()
this.validateForm()
await this.props.authenticate(this.state.email, this.state.password)
if(this.props.isAuthenticated) {
this.props.history.push('/dashboard')
return
}
if(!this.props.isAuthenticated){
this.setState({
formValidationState: 'error',
errorMessage: this.state.formIsValid &&
'Your password and/or email is not associated with an active user'
})
if(this.state.email && this.state.password){this.resetFields()}
}
}
validateForm(){
this.validateEmail()
this.validatePassword()
this.setState({
formIsValid: (this.state.emailValidationState === 'success'
&& this.state.passwordValidationState === 'success')})
}
validatePassword(){
const password = zxcvbn(this.state.password)
if(password.score >=0){
this.setState({
passwordValidationState: 'error',
passwordHelpText: password.feedback.suggestions})
return
}
this.setState({
passwordValidationState: 'success',
passwordHelpText: null })
}
validateEmail(){
if(!_.isEmpty(this.state.email)) {
this.setState({
emailValidationState: 'success',
emailError: ''
})
return
}
this.setState({
emailValidationState: 'error',
emailError: 'please enter an email address'
})
}
resetFields(){
this.setState({
email: '',
emailError: '',
emailValidationState: null,
password: '',
passwordHelpText: '',
passwordValidationState: null })
}
render(){
return(
<div>
<Login
email={this.state.email}
emailError={this.state.emailError}
emailValidationState={this.state.emailValidationState}
errorMessage={this.state.errorMessage}
formValidationState={this.state.formValidationState}
handleEmailInput={this.handleEmailInput}
handlePasswordInput={this.handlePasswordInput}
login={this.handleLoginPressed}
password={this.state.password}
passwordHelpText={this.state.passwordHelpText}
passwordValidationState={this.state.passwordValidationState}
/>
</div>
)
}
}
const mapStateToProps = state => ({
isAuthenticating: state.auth.isAuthenticating,
isAuthenticated: state.auth.isAuthenticated,
token: state.auth.token
})
export const mapDispatchToProps = {
authenticate: AsyncActions.authenticate
}
export { Login }
export default connect(mapStateToProps, mapDispatchToProps)(LoginContainer)
import React, { Component } from 'react'
import {
Button,
ControlLabel,
HelpBlock,
FormControl,
FormGroup,
PageHeader } from 'react-bootstrap'
登录表格
(请注意,我们只使用 onChange 电子邮件)
export default class LoginForm extends Component {
render(){
return (
<div className='ft-login-form'>
<PageHeader className='ft-header'><small>Login</small></PageHeader>
<form onSubmit={this.props.login}>
<FormGroup validationState={this.props.formValidationState}>
<ControlLabel className="ft-form-error-message">{this.props.errorMessage}</ControlLabel>
</FormGroup>
<FormGroup controlId="formBasicText" validationState={this.props.emailValidationState}>
<ControlLabel>Email</ControlLabel>
<FormControl
bsSize="small"
className="ft-username"
componentClass="input"
onChange={this.props.handleEmailInput}
placeholder="Enter email"
style={{ width: 300}}
type="email"
value={this.props.email}
/>
<HelpBlock className="ft-email-error">{this.props.emailError}</HelpBlock>
</FormGroup>
<FormGroup validationState={this.props.passwordValidationState}>
<ControlLabel>Password</ControlLabel>
<FormControl
bsSize="small"
className="ft-password"
componentClass="input"
onPaste={() => this.props.handleEmailPaste}
onChange={() => this.props.handlePasswordInput}
placeholder="Enter password"
style={{ width: 300}}
type="password"
value={this.props.password}
/>
<HelpBlock className="ft-password-help-text">{this.props.passwordHelpText}</HelpBlock>
</FormGroup>
<Button
className='ft-login-button'
type='submit'
>Login</Button>
</form>
</div>)
}
}
最佳答案
很高兴您意识到 onPaste
是错误的。这是解决方案的一半。 :)
你仍然缺少的是 setState
是一个异步函数。无论何时调用 setState
,您只是在排队新的状态数据。 react 如此强大的部分原因在于它的内在能力,事实上,采取多个 setState
函数并将它们合并为一个单一的更新(因此,一个单一的测试是否重新渲染)。
也就是说,setState
函数确实允许回调函数作为辅助参数。使用这些回调来指定应用新状态后应该做什么。它应该看起来像这样;
this.setState({email: e.target.value }, this.validateEmail)
关于javascript - 在 React 组件的文本框中复制文本的粘贴,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44558181/