使用字符串动态响应 setState

Posted

技术标签:

【中文标题】使用字符串动态响应 setState【英文标题】:React setState dynamically using string 【发布时间】:2020-04-20 19:41:57 【问题描述】:

如何在 React 组件中动态设置和存在状态字段?

我目前的尝试导致以下方法,但它在 TypeScript 中不起作用:

export interface MaskCompanyDetailState 
    fieldId: number;


export class MaskCompanyDetail extends React.Component<MaskCompanyDetailProps, MaskCompanyDetailState> 

    public constructor(props: any) 
        super(props);

        // Set field defaults.
        this.state = 
            fieldId: 0,
        ;
    

    public componentDidMount() 
        const myField: string = 'fieldId';
        const myVal: number = 123;
        this.setState([myField]: myVal);
        this.setState(myField: myVal);
    

来自 TSLint 的 this.setState([myField]: myVal); 的错误消息:

类型参数 ' [x: string]: number; ' 不可分配给“MaskCompanyDetailState |”类型的参数((prevState: Readonly, props: Readonly) => MaskCompanyDetailState | Pick<...>) |选择<...>'。 输入 ' [x: string]: number; ' 缺少“Pick”类型的以下属性:fieldId、fieldCompanyName、fieldStreetName、fieldStreetNumber 和 4 个以上。ts(2345)

来自 TSLint 的 this.setState(myField: myVal); 的错误消息:

类型参数 ' myField: number; ' 不可分配给“MaskCompanyDetailState |”类型的参数((prevState: Readonly, props: Readonly) => MaskCompanyDetailState | Pick<...>) |选择<...>'。 对象字面量只能指定已知属性,并且“myField”类型不存在于“MaskCompanyDetailState | ((prevState: Readonly, props: Readonly) => MaskCompanyDetailState | Pick<...>) |选择<...>'.ts(2345)

已经有帖子here了,但是我不知道如何应用建议的IState接口。

【问题讨论】:

您想为对象添加属性吗?或者你想使用myField 变量的值来动态设置属性名? 为什么myField 键周围有引号?有点违背了计算属性的要点,['myField']: 123myField: 123 相同,我认为这不是您想要做的,我猜myField 是一个变量,在这种情况下它应该是[myField]: 123 我已通过指定初始问题并提供更多代码来更新帖子。 切向相关:“TSLint”指的是现已弃用的单独工具。您可能指的是“TypeScript”。 【参考方案1】:

MaskCompanyDetailState接口中添加如下字段——

[key: string]: any;

即,

interface MaskCompanyDetailState 
    ... // existing fields
    [key: string]: any;

这意味着您允许在您的状态中设置具有string 类型的键和any 类型的值的任何属性。 这就是您链接的post 所说的。这是一个 Index Signature 的例子,它是 Typescript 的一个特性。

不建议这样做,因为从长远来看,它会影响代码的可读性,并且团队中的其他人可能会滥用它。但除了重新考虑您的设计之外,我不知道有任何其他解决方案可以解决您的困境。

【讨论】:

是否可以设置 readonly 以便可以读取/写入现有字段,但阻止在运行时创建新字段的可能性? [key: string]: any; 部分是索引签名,而不是真正的属性。我已编辑我的答案以包含更多信息的链接。虽然您可以将其设置为 readonly,但当您在代码中执行 this.setState([myField]: myVal); 时,您实际上是在运行时在状态中创建新的字段/属性。没有办法解决这个问题。 readonly 意味着您只能在状态上创建(并在数组的情况下进行变异)属性。 AFAIK,没有办法阻止人们在运行时使用Index Signature 创建新字段。我的建议是在MaskCompanyDetailState 中声明所有可能的字段,但将它们标记为可选,而不是使用Index Signature

以上是关于使用字符串动态响应 setState的主要内容,如果未能解决你的问题,请参考以下文章

调用 setState 后 ReactJS 元素未更新

用动态键反应 setState

Flutter:setState 在第一次尝试时工作,但在响应 = 等待后没有工作

如何使用 Javascript 中的动态链接数组发出多个 Axios 请求?

SetState 更新但不保存

在 React 中使用 push 方法的空数组 setState