javascript 对多个受控文本输入反应缓慢
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32911519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React slow with multiple controlled text inputs
提问by mrberggg
I have a form with multiple text inputs. I have them all set up as controlled inputs. When typing, there is a lag of up to several seconds for the new text to display in the field. Here is an example field:
我有一个包含多个文本输入的表单。我将它们全部设置为受控输入。键入时,新文本在字段中显示的延迟时间长达数秒。这是一个示例字段:
<label>Event Name</label>
<input type="text"
placeholder="Title"
className="form-control"
name="title"
value={this.state.event.title}
onChange={this.handleChange} />
I can't figure out what's causing it to be so slow or what to do to fix it.
我无法弄清楚是什么导致它如此缓慢或如何解决它。
UPDATED: Here's the component, should be enough to show what's going on.
更新:这是组件,应该足以显示正在发生的事情。
let CreateEventForm = React.createClass({
submit: function () {},
handleChange: function(e){
let value = e.target.value;
let name = e.target.name;
if(value === 'true'){
value = true;
}
if(value === 'false'){
value = false;
}
// If true/false toggle old
let oldState = this.state.event[name];
if(typeof oldState === 'boolean'){
value = !oldState;
}
// If is array
if(name.indexOf('[]') > -1){
name = name.replace('[]', '');
oldState = this.state.event[name];
var pos = oldState.indexOf(value);
if(pos > -1){
oldState.splice(pos, 1);
} else {
oldState.push(value);
}
value = oldState;
}
let event = this.state.event;
event[name] = value;
this.setState({event: event});
console.log(this.state.event);
},
getClasses(field, additionalClasses = []) {
// If a string is passed for additional class, make array
if(!Array.isArray(additionalClasses)){
additionalClasses = [additionalClasses];
}
let useDefaultColumns = additionalClasses.filter(function(className){
return className.indexOf('col-') > -1;
}).length === 0;
let hasError = function(){
let fields = Array.isArray(field) ? field : [field];
return fields.filter(function(field){
return !this.props.isValid(field);
}.bind(this)).length > 0;
}.bind(this)();
return classnames({
'col-sm-4': useDefaultColumns,
'form-group': true,
'has-error': hasError
}, additionalClasses);
},
render: function () {
return (
<form ref="eventForm" onSubmit={this.submit}>
<SavedModal isOpen={this.state.saved} reset={this.resetForm} style={this.state.modals.styles} />
<h3>Info</h3>
<div className="row">
<div className={this.getClasses('title')}>
<label>Event Name</label>
<input type="text" placeholder="Title"
className="form-control"
name="title"
value={this.state.event.title}
onChange={this.handleChange} />
{this.renderHelpText(this.props.getValidationMessages('title'))}
</div>
</div>
<div className="row">
<div className={this.getClasses('type')}>
<label>Event Type</label>
<select name="type"
className="form-control"
value={this.state.event.type}
onChange={this.handleChange}
onBlur={this.props.handleValidation('type')}>
<option value="">Select Event Type…</option>
{this.state.calendarTypes.map(function (type, key) {
return <option value={type.name} key={key}>{type.name}</option>
})}
</select>
{this.renderHelpText(this.props.getValidationMessages('type'))}
</div>
</div>
<h3>Duration</h3>
<div className="row">
<div className="form-group col-sm-2">
<input type="checkbox" name="allDay" checked={this.state.event.allDay} onChange={this.handleChange}/> All Day
</div>
</div>
<div className="row">
<div className="form-group col-sm-2">
<input type="checkbox" name="repeats" checked={this.state.event.repeats} onChange={this.handleChange}/> Repeats…
</div>
<br/><br/>
</div>
<h3>Location</h3>
<div className="row">
<div className={this.getClasses('location')}>
<select name="location"
className="form-control"
value={this.state.event.location}
onBlur={this.props.handleValidation('location')}
onChange={this.handleChange}>
<option value="">Select a Location…</option>
{this.state.locations.map(function (location, key) {
return (
<option value={location.name} key={key}>{location.name}</option>
);
})}
</select>
{this.renderHelpText(this.props.getValidationMessages('location'))}
</div>
</div>
<h3>Description</h3>
<div className="row">
<div className={this.getClasses('description')}>
<label>Write a description:</label>
<textarea className="form-control"
name="description"
value={this.state.event.description}
onChange={this.handleChange}
onBlur={this.props.handleValidation('description')}
rows="10"></textarea>
{this.renderHelpText(this.props.getValidationMessages('description'))}
</div>
</div>
<h3>Event Details</h3>
<div className="row">
<div className={this.getClasses('fee')}>
<label>Fee:</label>
<input type="text"
className="form-control"
name="fee"
value={this.state.event.fee}
onChange={this.handleChange}
onBlur={this.props.handleValidation('fee')}/>
{this.renderHelpText(this.props.getValidationMessages('fee'))}
</div>
</div>
<div className="row">
<div className="col-sm-12">
<button className="btn btn-primary" type="submit">
Create Event
</button>
</div>
</div>
</form>
);
}
});
采纳答案by mrberggg
Seeing as this still gets responses, thought I'd update this and close it. Calling handleChange
within onChange
would cause the entire form to rerender on every change, thereby slowing it down. If you had a simple form you could just update onBlur
instead or create individual input components so the rerender would be isolated to that one input. Personally, I use and would recommend using Formikfor building forms as it abstracts this complexity for you.
看到这仍然得到回应,我想我会更新并关闭它。调用handleChange
内onChange
将导致整个表单在每次更改时重新呈现,从而减慢速度。如果您有一个简单的表单,您可以onBlur
改为更新或创建单独的输入组件,以便重新渲染与该输入隔离。就我个人而言,我使用并推荐使用Formik来构建表单,因为它为您抽象了这种复杂性。
回答by Nek
I had a similar situation and my solution was to disable React Dev Tools. They were affecting input fields somehow. The problem is it's not enough to refresh a page if you have clicked React Dev Tools tab. They are still affecting your inputs. You have to open new page to stop them. You can also remove them from Chrome completely but I don't recommend doing this 'cause they are useful. :)
我遇到了类似的情况,我的解决方案是禁用 React Dev Tools。他们以某种方式影响输入字段。问题是如果您单击了 React Dev Tools 选项卡,则刷新页面是不够的。它们仍在影响您的输入。您必须打开新页面才能阻止它们。您也可以从 Chrome 中完全删除它们,但我不建议这样做,因为它们很有用。:)
回答by aks
There are many possible reasons for this to happen. I faced the similar issue and filtered the main cause to:
发生这种情况的可能原因有很多。我遇到了类似的问题,并将主要原因过滤为:
- Large State, so it takes up sometime
- React Dev Tool / Use of non minified react
- Mutating state data
- 大状态,所以它需要一些时间
- 反应开发工具/使用非缩小反应
- 改变状态数据
Whatever may be the reason, I found a quick fix for this. If you just want to store it to the state but not using it for live rendering. Then you can safely replace the 'onChange' to 'onBlur'. This has no dealay and lag. If you know any other case where this will not work, do let me know!
不管是什么原因,我找到了一个快速解决方法。如果您只想将其存储到状态而不是将其用于实时渲染。然后您可以安全地将“onChange”替换为“onBlur”。这没有延迟和滞后。如果您知道任何其他不起作用的情况,请告诉我!
Change the code as follow:
更改代码如下:
<label>Event Name</label>
<input
type="text"
placeholder="Title"
className="form-control"
name="title"
value={this.state.event.title}
onBlur={this.handleChange} />
回答by J. Mark Stevens
Here is an example for an input pattern, Plug in or pattern for dealing with large forms in React?. The main thing is to have your input as a component that passes changes to the parent but doesn't update from the props if they are the same.
这是一个输入模式的例子,插件或模式在 React 中处理大型表单?. 最重要的是将您的输入作为一个组件,将更改传递给父级,但如果它们相同,则不会从 props 更新。
回答by MCR
My problem was that my state object was complex and thus causing rendering issues. My solution was to manage the state of the notes in my component, then on blur update the container state.
我的问题是我的状态对象很复杂,从而导致渲染问题。我的解决方案是管理组件中笔记的状态,然后在模糊时更新容器状态。
const { data, onEdit } = props;
const { containerNotes } = data;
const [notes, setNotes] = useState('');
useEffect(
() => {
setNotes(containerNotes);
},
[containerNotes],
);
const onChangeNotes = () => ({ target: { value } }) => {
setNotes(value);
};
const onBlurNotes = (prop) => ({ target: { value } }) => {
const newData = update(data, {
[prop]: { $set: value },
});
onEdit(newData);
};
return (
<input
type="text"
placeholder="Title"
name="title"
value={notes}
onChange={onChangeNotes()}
onBlur={onBlurNotes('containerNotes')}
/>
)
回答by kir imi
Here is a fix I found. It sets the parent state in onBlur. Please vet this
这是我找到的修复程序。它在 onBlur 中设置父状态。请审核这个
import React, { useState } from 'react';
import MUIField from '@material-ui/core/TextField';
import _ from 'lodash';
export default (props) => {
const [value, setValue] = useState(props.defaultValue);
const prop = _.omit(props, ['onChange', 'value', 'defaultValue']);
return (
<MUIField {...prop} value={value}
onChange={e => { setValue(e.target.value); }}
onBlur={() => {
props.onChange({ target:{ value }});
}}/>);
};
回答by Sava B.
I've had redux logger middleware take enough time to create this input lag. So, try disabling that as well.
我已经让 redux logger 中间件花费了足够的时间来创建这个输入延迟。因此,请尝试禁用它。