spu*_*nge 20 text focus input ecmascript-6 reactjs
在下面的组件中,输入字段在输入字符后失去焦点.在使用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);
Run Code Online (Sandbox Code Playgroud)
文本输入组件
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;
Run Code Online (Sandbox Code Playgroud)
提交按钮组件
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;
Run Code Online (Sandbox Code Playgroud)
San*_*ane 32
原因如下:
我正在使用文本字段中的键。在同一个区块内;我有一个输入字段来更新同一文本字段的值。现在,由于组件键发生变化,react 会重新渲染 UI。因此失去焦点。
从中得到什么:
不要使用不断变化的键。
flo*_*oss 27
通过增加
autoFocus="autoFocus"
Run Code Online (Sandbox Code Playgroud)
在input为我工作的时候
<input
type="text"
autoFocus="autoFocus"
value = {searchString}
onChange = {handleChange}
/>
Run Code Online (Sandbox Code Playgroud)
Ser*_*ati 17
遇到了同样的问题并以一种快速简单的方式解决了它:只需调用组件{compName()}而不是<compName />
例如,如果我们有:
const foo = ({param1}) => {
// do your stuff
return (
<input type='text' onChange={onChange} value={value} />
);
};
const main = () => (
<foo param1={true} />
);
Run Code Online (Sandbox Code Playgroud)
然后,我们只需要改变我们调用foo()组件的方式:
const main = () => (
{foo({param1: true})}
);
Run Code Online (Sandbox Code Playgroud)
Ezr*_*ang 13
这是怎么回事:
当你的onChange事件触发时,回调调用带有新标题值的setState,该标题值作为prop传递给你的文本字段.那时,React重新渲染它,这就是你失去焦点的原因.
我的第一个建议是提供组件键,特别是表单和输入本身.密钥允许React通过渲染保留组件的标识.
Net*_*ogi 13
styled-components在功能组件内部使用时我遇到了类似的问题。每次我输入字符时,自定义输入元素都会失去焦点。
经过对代码进行大量搜索和实验后,我发现styled-components每次输入字符时,功能组件内部都会重新渲染输入字段,因为模板文字语法使表单成为一个函数,尽管它看起来像 Devtools 中的表达式。@HenryMueller的评论有助于让我朝着正确的方向思考。
我将样式组件移到功能组件之外,现在一切正常。
import React, { useState } from "react";
import styled from "styled-components";
const StyledDiv = styled.div`
margin: 0 auto;
padding-left: 15px;
padding-right: 15px;
width: 100%;
`;
const StyledForm = styled.form`
margin: 20px 0 10px;
`;
const FormInput = styled.input`
outline: none;
border: 0;
padding: 0 0 15px 0;
width: 100%;
height: 50px;
font-family: inherit;
font-size: 1.5rem;
font-weight: 300;
color: #fff;
background: transparent;
-webkit-font-smoothing: antialiased;
`;
const MyForm = () => {
const [value, setValue] = useState<string>("");
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
}
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if(value.trim() === '') {
return;
}
localStorage.setItem(new Date().getTime().toString(), JSON.stringify(value));
setValue('');
}
return (
<StyledDiv>
<StyledForm onSubmit={handleSubmit}>
<FormInput type="text"
id="inputText"
name="inputText"
placeholder="What Do You Want To Do Next?"
value={value}
onChange={handleChange}/>
</StyledForm>
</StyledDiv>
)
}
export default MyForm;
Run Code Online (Sandbox Code Playgroud)
styled-components在这种情况下,最好的使用方法是将它们保存在单独的文件中并导入它们。
小智 10
您必须为输入组件使用唯一键。
<input key="random1" type="text" name="displayName" />
Run Code Online (Sandbox Code Playgroud)
key="random1" 不能随机生成。例如,
<div key={uuid()} className='scp-ren-row'>
Run Code Online (Sandbox Code Playgroud)
uuid() 将为每次重新渲染生成一组新的字符串。这将导致输入失去焦点。
如果元素是在 .map() 函数中生成的,则使用索引作为键的一部分。
{rens.map((ren,i)=>{
return(
<div key={`ren${i+1}`} className='scp-ren-row'>
{ren}{i}
</div>)
}
Run Code Online (Sandbox Code Playgroud)
这将解决问题。
这是因为您正在render()中的函数中呈现表单。
每次状态/属性更改时,该函数都会返回一个新表格。它导致您失去焦点。
尝试将函数内部的内容直接放入渲染中。
<main id="main" role="main">
<div className="container-fluid">
<FormPostSingle />
</div>
</main>
Run Code Online (Sandbox Code Playgroud)
====>
<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>
Run Code Online (Sandbox Code Playgroud)
小智 6
我也有这个问题,我的问题与使用另一个组件来包装 textarea 有关。
// 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
Run Code Online (Sandbox Code Playgroud)
当状态改变时,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
Run Code Online (Sandbox Code Playgroud)
我注意到人们经常将本地使用的组件放在想要使用它的组件中。通常利用函数作用域并获得对父组件 props 的访问权限。
const ParentComp = ({ children, scopedValue }) => {
const ScopedComp = () => (<div>{ scopedValue }</div>)
return <ScopedComp />
}
Run Code Online (Sandbox Code Playgroud)
我从来没有真正想过为什么需要这样做,因为您可以将道具钻到内部函数中,然后从父组件中将其外部化。
这个问题是一个完美的例子,说明为什么您应该始终将组件相互外部化,即使它们在一个模块中使用。此外,您始终可以使用智能文件夹结构来保持附近的事物。
src/
components/
ParentComp/
ParentComp.js
components/
ScopedComp.js
Run Code Online (Sandbox Code Playgroud)