如何更改 Typescript class 实例中的值?
How do I change a value in an instance of a Typescript class?
我有一个水果class:
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
但是当我点击按钮时,屏幕上的水果名称并没有改变。它保持为 'apple' 。有谁知道我做错了什么?我是 Typescript 的新手
一些注意事项:
React 功能组件不是那样工作的。如果你的数据随时间变化,你需要定义一些状态,用一个钩子:const [fruit, setFruit] = React.useState(initialFruit)
.
这仍然行不通,因为您的 fruit
是一个可变对象,React 不会“看到”就地命令更新。不理想,但你可以通过使用对象包装器作为状态值来欺骗 React:{ value: someFruit }
(这是有效的,因为在 JS 中 { value: 1 } !== { value: 1 }
.
如您所见,React 的整个思想涉及不可变值(也称为函数式编程)。考虑用不可变的设置器 (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)
}
}
事情是这样的。这行不通。
首先,在 React 功能组件的渲染函数中创建的任何变量仅在该渲染期间存在。所以当你这样做时:
let fruit = new Fruit(1, 'apple')
然后,每次您的组件呈现时,您都会创建一个新的 Fruit
,其 id
为 1
,名称为 "apple"
。您在渲染后对 object 所做的任何更改将永远不会被看到,因为要看到该组件需要 re-rerender,这会从头开始创建一个新的 Fruit
。
解决这个问题的方法是使用“state”,它保留组件渲染之间的值。
所以,假设你有这个:
const HomePage = () => {
let [fruit, setFruit] = useState(new Fruit(1, 'apple'))
//...
}
但问题是状态应该是 不可变的,这意味着如果状态要改变,它需要一个新的 object 完全,并且它被禁止换一块状态。
这是因为除非您完全替换状态,否则 React 无法判断状态是否真的发生了变化。
因此,要解决此问题,您需要在更改状态时设置全新的 object。
这应该有效:
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>
)
}
但这真是个烦人的孩子。这就是为什么不建议将可变实例放入状态的原因。这意味着通常根本不需要 class 的实例,而且将 object 存储在状态中通常要简单得多。
// declare state
let [fruit, setFruit] = useState({ id: 1, name: 'apple' })
// set state
setFruit({ ...fruit, name: 'banana' })
我有一个水果class:
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
但是当我点击按钮时,屏幕上的水果名称并没有改变。它保持为 'apple' 。有谁知道我做错了什么?我是 Typescript 的新手
一些注意事项:
React 功能组件不是那样工作的。如果你的数据随时间变化,你需要定义一些状态,用一个钩子:
const [fruit, setFruit] = React.useState(initialFruit)
.这仍然行不通,因为您的
fruit
是一个可变对象,React 不会“看到”就地命令更新。不理想,但你可以通过使用对象包装器作为状态值来欺骗 React:{ value: someFruit }
(这是有效的,因为在 JS 中{ value: 1 } !== { value: 1 }
.如您所见,React 的整个思想涉及不可变值(也称为函数式编程)。考虑用不可变的设置器 (
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)
}
}
事情是这样的。这行不通。
首先,在 React 功能组件的渲染函数中创建的任何变量仅在该渲染期间存在。所以当你这样做时:
let fruit = new Fruit(1, 'apple')
然后,每次您的组件呈现时,您都会创建一个新的 Fruit
,其 id
为 1
,名称为 "apple"
。您在渲染后对 object 所做的任何更改将永远不会被看到,因为要看到该组件需要 re-rerender,这会从头开始创建一个新的 Fruit
。
解决这个问题的方法是使用“state”,它保留组件渲染之间的值。
所以,假设你有这个:
const HomePage = () => {
let [fruit, setFruit] = useState(new Fruit(1, 'apple'))
//...
}
但问题是状态应该是 不可变的,这意味着如果状态要改变,它需要一个新的 object 完全,并且它被禁止换一块状态。
这是因为除非您完全替换状态,否则 React 无法判断状态是否真的发生了变化。
因此,要解决此问题,您需要在更改状态时设置全新的 object。
这应该有效:
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>
)
}
但这真是个烦人的孩子。这就是为什么不建议将可变实例放入状态的原因。这意味着通常根本不需要 class 的实例,而且将 object 存储在状态中通常要简单得多。
// declare state
let [fruit, setFruit] = useState({ id: 1, name: 'apple' })
// set state
setFruit({ ...fruit, name: 'banana' })