【问题标题】:How to Use One handleChange Event for Multiple TextFields?如何为多个文本字段使用一个 handleChange 事件?
【发布时间】:2020-07-14 12:36:06
【问题描述】:

在以下代码中,我将“供应商名称”文本字段设置为所有大写字母。如果我想将此添加到“评论”文本字段中,我知道我可以添加更多的 handleChange 事件并以不同的方式命名它们。有没有办法对多个 TextField 使用相同的 handleChange 事件,因为我想做完全相同的事情?

import * as React from "react";
import { TextField} from 'office-ui-fabric-react/lib/TextField';
export interface StackOverflowState {
    value: string;
  }
  export default class StackOverflow extends React.Component<{}, StackOverflowState> {
    public state: StackOverflowState = { value: '' };
    render() {
      this.handleChange = this.handleChange.bind(this);
      ;

      return (
        <div className="ms-welcome">
            <TextField 
                label="Supplier Name"
                styles={{ root: { width: 150 } }}
                onChange={this.handleChange.bind(this)}
                value={this.state.value}
            />
            <TextField 
                label="Comments"
                styles={{ root: { width: 300 } }}
            />
        </div>
      );
    }
    handleChange(event) {
      this.setState({value: event.target.value.toUpperCase()});
    }
  }

【问题讨论】:

    标签: reactjs typescript office-js office-ui-fabric tsx


    【解决方案1】:

    您可以将对象用作状态,其中包含键作为字段名称和值对各自的字段名称

    state = { values : {} };
    
    onChange = (name, e) => {
       this.setState(state => ({ values: { ...state.values, [name]: e.target.value } }));
    
      // If e.target.name contains field name, no need to add extra name parameter in this method, you can use that as name
    
    }
    
         <TextField 
                label="Supplier Name"
                styles={{ root: { width: 150 } }}
                onChange={e => this.handleChange('supplierName', e)}
                value={this.state.values.supplierName}
            />
     <TextField 
                label="Comments"
                styles={{ root: { width: 300 } }}
                onChange={e => this.handleChange('comments', e)}
                value={this.state.values.comments}
            />
    

    【讨论】:

    • 感谢您的回复!我在哪里将 onChange 事件放在顶部?以及为了 state = { value: {} } 我要删除什么;上班?
    【解决方案2】:

    多尝试使用绑定 :)

    import * as React from "react";
    import { TextField} from 'office-ui-fabric-react/lib/TextField';
    export interface StackOverflowState {
        value: string;
        comments: string;
      }
      export default class StackOverflow extends React.Component<{}, StackOverflowState> {
        public state: StackOverflowState = { value: '', comments: '' };
    
        private const handleChange = (stateField: keyof StackOverflowState) => (event) {
          this.setState({ [stateField]: event.target.value.toUpperCase()});
        }
    
        render() {
          return (
            <div className="ms-welcome">
                <TextField 
                    label="Supplier Name"
                    styles={{ root: { width: 150 } }}
                    onChange={this.handleChange('value')}
                    value={this.state.value}
                />
                <TextField 
                    label="Comments"
                    onChange={this.handleChange.('comments')}
                    styles={{ root: { width: 300 } }}
                />
            </div>
          );
        }
      }
    
    

    【讨论】:

    • 感谢您的回复!我收到一个错误,类型为 '{ [x: string]: any; 的 [stateField] 参数}' 不能分配给“StackOverflowState |”类型的参数((prevState: Readonly, props: Readonly) => StackOverflowState | Pick<...>) |选择<...>'。
    • 总的来说,我认为最好有两种方法,而不是这种情况下的一种,除非你有很多字段(在这种情况下,我相应地更新了类型)
    【解决方案3】:

    一些注意点:

    • 不要在 render() 中使用.bind(this),可以选择使用箭头函数。
    • 使用constructor() 初始化经典组件的状态。
    • 带有标识索引的通用处理函数已作为参数传递。
    • 使用[key: string]: State[keyof State] 启用按字符串选择属性。

    此外,我们可以:

    • 使用状态数组
    • 使用本地 HOC 避免在索引上重复自己
    • 使用数组生成渲染元素
    import * as React from "react";
    import { TextField } from "office-ui-fabric-react/lib/TextField";
    
    export interface State {
      [key: string]: State[keyof State];
      inputA: string;
      inputB: string;
    }
    export default class App extends React.Component<{}, State> {
      constructor(props: {}) {
        super(props);
        this.state = {
          inputA: "",
          inputB: ""
        };
      }
      handleChange = (field: string) => (event: any) => {
        const value = event.target.value.toUpperCase();
        this.setState({ [field]: value });
      };
      render() {
        console.log(this.state);
        return (
          <div className="ms-welcome">
            <TextField
              label="Supplier Name"
              styles={{ root: { width: 150 } }}
              onChange={this.handleChange("inputA")}
              value={this.state["inputA"]}
            />
            <TextField
              label="Comments"
              styles={{ root: { width: 300 } }}
              onChange={this.handleChange("inputB")}
              value={this.state["inputB"]}
            />
          </div>
        );
      }
    }
    

    【讨论】:

    【解决方案4】:

    使用单个事件处理程序处理多个输入。您必须为输入值提供唯一名称,并且可以根据唯一名称编写句柄更改。

    <div className="ms-welcome">
            <TextField 
                name="input1"
                onChange={this.handleChange.bind(this)}
                value={this.state.value}
            />
            <TextField 
                name="input2"
                onChange={this.handleChange.bind(this)}
                value={this.state.value}
            />
        </div>
    

    现在您可以简单地根据应用于输入字段的唯一名称编写句柄更改

    HandleChange (e) {
     this.setState({[e.target.name]: e.target.value})
    }
    

    当事件来自第一个输入时,e.target.name 将是 input1,当事件来自第二个输入时,e.target.name 将是 input2。

    【讨论】:

    • 感谢您的回复!我收到 [e.target.name] 的错误:e.target.value Argument of type '{ [x: string]: any; }' 不能分配给“StackOverflowState |”类型的参数((prevState: Readonly, props: Readonly) => StackOverflowState | Pick<...>) |选择<...>'。
    猜你喜欢
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多