如何更改Typescript类示例中的值?

1l5u6lss  于 2023-05-19  发布在  TypeScript
关注(0)|答案(2)|浏览(137)

我有一个水果类:

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

但是当我点击按钮时,屏幕上的水果名称并没有改变。它仍然是“苹果”。有人知道我做错了什么吗?我是打字新手

piok6c0g

piok6c0g1#

一些注意事项:

  • React函数组件不是这样工作的。如果你的数据随着时间的推移而变化,你需要定义一些状态,用一个钩子:const [fruit, setFruit] = React.useState(initialFruit) .
  • 这仍然不起作用,因为你的fruit是一个可变对象,React不会“看到”就地命令式更新。这并不理想,但你可以通过使用对象 Package 器作为状态值来欺骗React:{ value: someFruit }(这是因为在JS { value: 1 } !== { value: 1 }中。
  • 考虑使用不可变的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)
    }
}
e3bfsja2

e3bfsja22#

事情是这样的这样没用的
首先,在react函数组件的render函数中创建的任何变量都只存在于该渲染期间。当你这样做时:

let fruit = new Fruit(1, 'apple')

然后,每次渲染组件时,您都会创建一个新的Fruit,其id1,名称为"apple"。渲染后对该对象所做的任何更改都将永远不会被看到,因为要看到组件,需要重新渲染,这将从头开始创建一个新的Fruit
解决这个问题的方法是使用“状态”,它在组件渲染之间保留值。
所以,假设你有这个:

const HomePage = () => {
    let [fruit, setFruit] = useState(new Fruit(1, 'apple'))
    //...
}

但问题是,状态应该是“不可变的”,这意味着如果状态要改变,它会期望一个全新的对象,并且禁止改变状态的一部分。
这是因为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' })

相关问题