You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React受控TextField输入字符后失焦,如何修复该问题?

解决受控TextField输入时失去焦点的问题

这个问题的根源在于你在Config和MenuEntry组件的render方法里直接修改了组件实例的属性(this.owner = owner、this.value = value),这违反了React中render方法应该是纯函数的原则。

为什么会导致焦点丢失?

每次你在输入框输入字符时,会触发setUrl方法修改父组件的state,父组件随之重新render。这时候子组件Config的render方法会再次执行,你在这里给this.owner重新赋值的操作,会让React误以为当前的Config组件是一个全新的实例,于是会卸载旧的组件再重新挂载新的——旧的输入框被销毁,新的输入框自然就失去焦点了。

修复方案

我们需要移除render中对组件实例属性的赋值,直接通过this.props访问父组件传递过来的值。

修改后的Config组件:

"use strict"
import React from "react";
import createReactClass from "create-react-class";
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';
import {Card, CardActions, CardHeader, CardMedia, CardTitle, CardText} from 'material-ui/Card';

export var Config = createReactClass({
  setConfig: function() {
    localStorage.serverUrl = this.props.owner.state.serverUrl;
    location.reload();
  },
  setUrl: function(evt) {
    // 直接通过props访问父组件,不再依赖this.owner
    this.props.owner.setState({serverUrl: evt.target.value});
  },
  render: function() {
    const { owner } = this.props;
    // 移除this.owner = owner的赋值操作
    return (
      <div>
        <CardTitle title={__("Server")} />
        <CardText>
          <TextField 
            id="serverUrl" 
            floatingLabelText={__("Server URL")} 
            value={owner.state.serverUrl} 
            onChange={this.setUrl} 
          />
        </CardText>
        <CardActions>
          <RaisedButton label={__("Apply")} onTouchTap={this.setConfig} />
        </CardActions>
      </div>
    );
  }
});

修改后的MenuEntry组件:

"use strict";
import React from "react";
import createReactClass from "create-react-class";
import MenuItem from 'material-ui/MenuItem';

export var MenuEntry = createReactClass({
  onChange: function() {
    const { owner, value } = this.props;
    // 直接从props获取所需值,不再依赖this.owner和this.value
    owner.setState({
      menuOpen: false, 
      systemMenuOpen: false, 
      location: value
    });
  },
  render: function() {
    const { title, owner, value, color } = this.props;
    // 移除this.owner和this.value的赋值操作
    const selected = owner.state.location === value;
    return (
      <MenuItem 
        checked={selected} 
        onTouchTap={this.onChange} 
        backgroundColor={color}
      >
        {title}
      </MenuItem>
    );
  }
});

额外优化建议(可选)

为了让组件耦合度更低,更符合React的单向数据流原则,建议不要让子组件直接修改父组件的state,而是由父组件传递回调函数给子组件。比如:

  1. 在父组件中定义处理URL变化的方法:
handleServerUrlChange = (url) => {
  this.setState({ serverUrl: url });
}
  1. 把这个方法传递给Config组件:
<Config owner={this} onServerUrlChange={this.handleServerUrlChange} />
  1. 在Config组件中调用这个回调:
setUrl: function(evt) {
  this.props.onServerUrlChange(evt.target.value);
}

这样修改后,输入框在输入时就不会再丢失焦点了。

内容的提问来源于stack exchange,提问作者Ruediger Jungbeck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:49:44