首页 > 解决方案 > React/Redux,从模型调用方法抛出 TypeError

问题描述

我正在尝试从模型运行 formatAddress,以格式化的方式显示地址,但只要调用该方法,它就会抛出 TypeError。

零件

export const PostRow: React.FC<Props> = ({ index, userIndex }) => {
    const dispatch = useDispatch()
    const { name, username, email, formatAddress } = useSelector((state: RootState) => state.users[userIndex])
    console.log(formatAddress())

减速器


export const userReducer: Reducer<UserState, UserActions> = (state: UserState = [], action: UserActions): UserState => {
    switch (action.type) {
        case UserActionTypes.GET_ALL_USERS:
            return action.payload.map((user: UserResponseDTO) => (new User(user)))
        default:
            return state
    }
}

模型

export class User {
    public id: number
    public name: string
    public username: string
    public email: string
    public address: UserAdress
    public phone: string
    public website: string
    public company: UserCompany

    constructor(userDTO: UserResponseDTO) {
        this.id = userDTO.id
        this.name = userDTO.name
        this.username = userDTO.username
        this.email = userDTO.email
        this.address = userDTO.address
        this.phone = userDTO.phone
        this.website = userDTO.website
        this.company = userDTO.company
    }

    formatAddress() {
        return `${this.address.street}. ${this.address.city} - ${this.address.zipcode}`
    }
}

退货

TypeError: Cannot read property 'address' of undefined

标签: javascriptreactjstypescriptredux

解决方案


对于常规函数, 的值this取决于函数的调用方式。由于您已将 formatAddress 保存到变量中,然后使用 code 调用它formatAddress(),因此在没有任何上下文的情况下调用它。结果,this默认为未定义(或在非严格模式下,为窗口对象)。

一种选择是更改您的调用方式。如果你保存用户对象然后调用user.formatAddress(),那么this将被设置为等于用户:

const user = useSelector((state: RootState) => state.users[userIndex]);
console.log(user.formatAddress());

或者,您可以将 formatAddress 绑定到用户。这将创建一个新函数,其值this永久存在:

constructor(userDTO: UserResponseDTO) {
  this.id = userDTO.id
  // ... etc
  this.company = userDTO.company
  this.formatAddress = this.formatAddress.bind(this);
}

或者使用箭头函数,因为它们是thisthis创建箭头函数时获得的。由于您使用的是打字稿,因此可以使用以下语法:

export class User {
  // ... stuff omitted
  constructor(userDTO: UserResponseDTO) {
    //...
  }

  formatAddress = () => {
    return `${this.address.street}. ${this.address.city} - ${this.address.zipcode}`
  }
}

推荐阅读