【问题标题】:Typescript & ReactJS How To Dynamically Set StateTypescript & ReactJS 如何动态设置状态
【发布时间】: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,
    }))
  };

有效!

【问题讨论】:

标签: reactjs typescript types


【解决方案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>);
    

    与此问题相关的错误:

    【讨论】:

    • 感谢您的链接!我的解决方案来自第二个链接: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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-16
        • 2020-02-09
        • 2014-09-23
        • 2019-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-17
        相关资源
        最近更新 更多