Typescript & ReactJS 如何动态设置状态
Posted
技术标签:
【中文标题】Typescript & ReactJS 如何动态设置状态【英文标题】:Typescript & ReactJS How To Dynamically Set State 【发布时间】:2019-04-02 01:21:16 【问题描述】:我将此接口定义为我的状态:
interface State
id: string;
name: string;
description: string;
dimensionID: string;
file: File | null;
operator: string;
isFormValid: boolean;
filename: string;
;
我有一个简单的变更处理程序:
update = (event: React.FormEvent<htmlInputElement>): void =>
const name, value = event.currentTarget;
this.setState( [name]: value );
;
但是,这个错误被抛出:
Error:(109, 19) TS2345: Argument of type ' [x: string]: string; ' is not assignable to parameter of type 'State | Pick<State, "id" | "name" | "description" | "dimensionID" | "file" | "operator" | "isFormValid" | "filename"> | ((prevState: Readonly<State>, props: Readonly<Props>) => State | Pick<...>)'.
Type ' [x: string]: string; ' is not assignable to type '(prevState: Readonly<State>, props: Readonly<Props>) => State | Pick<State, "id" | "name" | "description" | "dimensionID" | "file" | "operator" | "isFormValid" | "filename">'.
Type ' [x: string]: string; ' provides no match for the signature '(prevState: Readonly<State>, props: Readonly<Props>): State | Pick<State, "id" | "name" | "description" | "dimensionID" | "file" | "operator" | "isFormValid" | "filename">'.
我的问题是:如何像我的 on change 处理程序尝试那样动态设置状态? 此处理程序用于表单的不同部分,因此我不知道需要更新哪个状态键。
更新:解决方案 从这个post
update = (event: React.FormEvent<HTMLInputElement>): void =>
const name, value = event.currentTarget;
this.setState(prevState => (
...prevState,
[name]: value,
))
;
有效!
【问题讨论】:
在你调用更新的地方绑定名字。this.update.bind(null, name )
。这样在更新函数中,您将同时拥有名称和事件作为参数
看看这个:github.com/DefinitelyTyped/DefinitelyTyped/issues/…
【参考方案1】:
例如。
update = (name: string, event: React.FormEvent<HTMLInputElement>): void =>
const value = event.currentTarget;
this.setState( [name]: value );
;
<input onChange=this.update.bind(null, 'first_name') value=this.state.first_name />
【讨论】:
【参考方案2】:常量name 扩展为字符串。您使用的是哪个版本的 TS?
您可以这样投射,但这不是一个好习惯:
this.setState(
[name]: value
as Pick<State, keyof State>);
与此问题相关的错误:
https://github.com/Microsoft/TypeScript/issues/15534 https://github.com/Microsoft/TypeScript/issues/13948 https://github.com/DefinitelyTyped/DefinitelyTyped/issues/26635【讨论】:
感谢您的链接!我的解决方案来自第二个链接:github.com/Microsoft/TypeScript/issues/… 看来这与我遇到的问题相同。不过,看起来它并没有用最新版本解决。我正在使用 v3.0.1。【参考方案3】:您可以使用in keyof
关键字从 IState 对象中解构键/值。
创建你的 React 状态:
interface IState "email" : string;
创建一个表单类型,将键解构为 K,值解构为 T[K]:
type FormState<T> = [K in keyof T]: T[K] ;
// T represents your IState
// to get the key use: [K in keyof T]
// to reference the value use: T[K]
然后将 IState 作为泛型类型参数传递给 FormState 类型:
FormState<IState>
现在您可以更新状态,将其转换为上述 FormState:
this.setState( [formStateItem]: (e.target.value as any) as FormState<IState>);
在处理程序中可能如下所示:
handleChange = <T, K extends keyof IState>(formStateItem: K) =>
return (e: ChangeEvent<HTMLInputElement>) =>
this.setState( [formStateItem]: (e.target.value as any) as FormState<IState>);
;
最后你可以像这样在你的 JSX 中使用:
onChange=this.handleChange("email")
【讨论】:
【参考方案4】:最喜欢的解决方案铸造。
this.setState([name]: value as [P in keyof State]: State[P])
// or
this.setState([name]: value as Pick<State, keyof State>)
setState 传播前一个状态
this.setState((prevState) => ( ...prevState, [name]: value ));
这不检查类型。对于任何被困在转换中的人来说,这只是一个快速的解决方法。
this.setState<never>([name]: value)
相关链接
React setState
Github Tim Roes comment
【讨论】:
以上是关于Typescript & ReactJS 如何动态设置状态的主要内容,如果未能解决你的问题,请参考以下文章
TypeError:fs.existsSync 不是函数(Electron/ReactJS/Typescript)
缺少元素的“关键”道具。 (ReactJS 和 TypeScript)
在 ReactJS + Typescript 中加载 CSS 模块并重新连接反应