如何更改 Typescript 类实例中的值?
Posted
技术标签:
【中文标题】如何更改 Typescript 类实例中的值?【英文标题】:How do I change a value in an instance of a Typescript class? 【发布时间】:2022-01-20 16:41:41 【问题描述】:我有一个水果课:
export class Fruit
constructor(public id: number, public name: string)
public changeName(_name: string): void
console.log('changing name')
this.name = _name
我是这样实现的:
import React from 'react'
import Fruit from '../classes/fruit'
const HomePage = () =>
let fruit = new Fruit(1, 'apple')
return (
<div>
fruit.name <----- I am expecting this to update on the DOM when i click the button *********
<button onClick=() => fruit.changeName('banana')>
change the name
</button>
</div>
)
export default HomePage
但是当我点击按钮时,屏幕上的水果名称并没有改变。它保持为“苹果”。有谁知道我做错了什么?我是打字稿的新手
【问题讨论】:
【参考方案1】:一些注意事项:
React 函数式组件不是这样工作的。如果你的数据随时间变化,你需要定义一些状态,用一个钩子:const [fruit, setFruit] = React.useState(initialFruit)
。
这仍然行不通,因为您的 fruit
是一个可变对象,React 不会“看到”就地命令式更新。不理想,但你可以通过使用对象包装器作为状态值来欺骗 React: value: someFruit
(这是因为在 JS 中 value: 1 !== value: 1
。
如您所见,React 的整个想法涉及不可变值(AKA 函数式编程)。考虑使用不可变的 setter (public changeName(name: string): Fruit
) 编写类,您将能够编写像这样的漂亮声明性代码:<button onClick=() => setFruit(fruit.changeName('banana'))>
。
export class Fruit
constructor(public id: number, public name: string)
public changeName(name: string): Fruit
return new Fruit(this.id, name)
【讨论】:
我 99% 都在跟踪你,但我似乎无法编译它。我不确定您在哪里创建用于设置 useState 等的新类实例,或者即使您正在创建一个类实例以设置为 useState。无论如何,您可以为您的示例提供允许声明式 changeName 调用的代码? 不确定我是否遵循,但这不是一种 hacky 方法,即使不使用 React,您也不会触及现有对象,而是创建新对象。在不可变类上,“setter”只返回新实例。这就是函数式方法,它通常会产生更具声明性、更清晰的代码,因为您可以遵循工作流程,而不会在整个代码库中发生就地更新。在 google 中搜索“javascript 函数式编程不可变”。 > 您是否认为在类中也有相关方法的价值。是的,一个对象应该提供生命周期/更新方法;否则,使用它的代码会更加冗长,并且通常会破坏封装。 确实,这些是不同的东西。您必须创建新值以便 React 重新渲染,这就是重点。它的完成方式(使用虚拟 DOM 或其他)是一个实现细节。 没错:在 React 中,副作用只能在useEffect
块内执行。您可以在类中添加一个有效的save
方法,或者您可以创建一个someFruitRepository.save(fruit)
来隔离持久性的模型/实体(这是一个实现细节)。在某些时候,您可以深入研究 hex/clean 架构。【参考方案2】:
所以,事情就是这样。这是行不通的。
首先,在 react 功能组件的渲染函数中创建的任何变量仅在该渲染期间存在。所以当你这样做时:
let fruit = new Fruit(1, 'apple')
然后,每次您的组件渲染时,您都会创建一个新的Fruit
,其名称为1
的id
,名称为"apple"
。您在渲染后对该对象所做的任何更改都不会被看到,因为要看到组件需要重新渲染,这会从头开始创建一个新的Fruit
。
解决这个问题的方法是使用“状态”,它在组件渲染之间保留值。
所以,假设你有这个:
const HomePage = () =>
let [fruit, setFruit] = useState(new Fruit(1, 'apple'))
//...
但问题是状态应该是不可变的,这意味着如果状态要改变,它需要一个完全新的对象,并且禁止改变状态的一部分。 p>
这是因为除非你完全替换状态,否则 react 无法判断状态是否真正发生了变化。
所以要解决这个问题,您需要在更改状态时设置一个全新的对象。
这应该可行:
const HomePage = () =>
let [fruit, setFruit] = useState(new Fruit(1, 'apple'))
return (
<div>
fruit.name
<button onClick=() => setFruit(new Fruit(fruit.id, 'banana')>
change the name
</button>
</div>
)
但那是烦人的孩子。这就是为什么不建议将可变实例置于状态中的原因。这意味着通常根本不需要类的实例,而且将对象存储在状态中通常要简单得多。
// declare state
let [fruit, setFruit] = useState( id: 1, name: 'apple' )
// set state
setFruit( ...fruit, name: 'banana' )
【讨论】:
以上是关于如何更改 Typescript 类实例中的值?的主要内容,如果未能解决你的问题,请参考以下文章
如何在angular 2 typescript项目中更改body类
React Typescript:在 React.FC 中设置状态以更改 React.Component 中的值
Typescript Angular - Observable:如何更改其值?
Material-UI Typescript 如何在组件类中从 makeStyle() 创建样式实例