在ReactJs应用中处理onChange

3

我目前有一个带有一些输入框的React tsx页面;例如:

<textarea value={this.state.myData!.valueOne}
    onChange={(e) => this.handleValueOneChange(e)}/>

<textarea value={this.state.myData!.valueTwo}
    onChange={(e) => this.handleValueTwoChange(e)}/>

handleValueOneChangehandleValueTwoChange几乎完全相同:

handleValueOneChange(event: React.FormEvent<HTMLTextAreaElement>) {
    let newState = { ...this.state };

    newState.myData!.valueOne = event.currentTarget.value;
    this.setState(newState);
}

handleValueTwoChange(event: React.FormEvent<HTMLTextAreaElement>) {
    let newState = { ...this.state };

    newState.myData!.valueTwo = event.currentTarget.value;
    this.setState(newState);
}

是否有可能为这两个事件编写一个单一的函数?例如:

handleDataChange(event: React.FormEvent<HTMLTextAreaElement>, valueByRef) {
    let newState = { ...this.state };

    valueByRef = event.currentTarget.value;
    this.setState(newState);
}

我对TypeScript中可能的实现不是很清楚:我想做的事情是否可行,如果可以,应该怎么做?

编辑:

更复杂的是,myData包含了多种类型(这似乎是TS的一个问题)。

3个回答

0
当然,可以返回一个字符串,例如:
<Input onChange={(event)=>this.handleChange(event, 'type1')} />

我该如何使用该字符串来引用状态的属性? - user9530048

0

尝试类似这样的东西

HTML 变成了

<textarea value={this.state.myData!.valueOne}
    onChange={(e) => this.handleValueChange(e, 'valueOne')}/>

<textarea value={this.state.myData!.valueTwo}
    onChange={(e) => this.handleValueChange(e, 'valueTwo')}/>

并且逻辑(我猜你的状态类型为MyState)

handleDataChange<K extends keyof MyDataType>(event: React.FormEvent<HTMLTextAreaElement>, ref: K) {
    let newState = { ...this.state };

    newState.myData![ref] = event.currentTarget.value;
    this.setState(newState);
}

编辑:

根据评论,我修正了答案。

编辑: 如果myData包含字符串、数字和布尔值,您可以使用类型保护和转换。

handleDataChange<K extends keyof MyDataType>(event: React.FormEvent<HTMLTextAreaElement>, ref: K) {
    let newState = { ...this.state };

    let old = newState.myData![ref];
    if (typeof old === "number") newState.myData![ref] = parseInt(event.currentTarget.value); /* or parseFloat, this depends on your app */
    else if (typeof old === "boolean") newState.myData![ref] = (event.currentTarget.value === "1"); /* use any string -> boolean conversion function */
    else newState.myData![ref] = event.currentTarget.value; /* string case */
    this.setState(newState);
}

这会产生错误:(TS) 类型“string”不能赋值给类型“{ myState: MyState; }[K]”。类型“string”与类型“MyState”没有共同的属性。在handleDataChange上。我猜这是因为属性不直接在状态上,而是MyData的子类型的属性...? - user9530048
@qwerty,你说得对,我应该更新答案来解决这个问题,请告诉我这是否可行。 - Keilath
不行 - 我试过了(并稍微更新了我的问题)。我在那里得到的错误是“类型字符串无法从数字|未定义分配”。我猜这是因为MyData包含字符串、数字和布尔数据? - user9530048
@qwerty event.currentTarget.value 总是一个字符串,如果您的属性是另一种类型,则必须相应地进行转换。 - Keilath

0
如果您为文本区域添加一个名称属性,您可以使用该名称将值添加到状态中。
handleChange(event: React.FormEvent<HTMLTextAreaElement) {
    this.setState({
      ...this.state.myData,
      [event.currentTarget.name]: event.currentTarget.value,
    })
  }


<textarea value={this.state.myData.one} name="one"
   onChange={this.handleChange} />

<textarea value={this.state.myData.two} name="two"
   onChange={this.handleChange} />

onChange 属性在这种情况下看起来更清晰。没有使用内联箭头函数。

工作代码沙盒 https://codesandbox.io/s/04rm89oq8w


这给了我一个错误:对象文字只能指定已知属性,而'valueOne'在类型'Pick<MyState,"myData">'中不存在。此外,这里的链接已失效。 - user9530048

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接