React Native自定义类未设置属性

3

我创建了一个名为UserInfo的类,其中我将用户信息存储在变量中,并在不同的屏幕中调用这些变量。

    class UserInfo {
    constructor(props) {
        this.username = "Test"
    }
}

export default (new UserInfo())

我现在需要将用户信息从本地数据库中获取,因此我在UserInfo类中创建了一个方法来从本地数据库中获取数据。

我可以在其他屏幕上使用UserInfo.username来调用它并且它能正常工作。

    class UserInfo {
    constructor(props) {
        this.username = ""
        this.getUserInfo
    }

    getUserInfo = () =>{
        db.transaction((tx) => {
            tx.executeSql('SELECT * FROM users', [], (tx, results) => {
                let row = results.rows.item(0);
                console.log("UserID: " + row.id) // return value from db, working
                this.username = row.id
            });
        });
    }

}

export default (new UserInfo())

但是现在它返回空值,但控制台上显示了值,我有什么遗漏吗?我通过在构造函数末尾调用getUserInfo方法重新设置了用户名的值...


你需要调用方法 this.getUserInfo() 而不是 this.getUserInfo - Mukesh Soni
已经尝试过了,结果还是一样... - DIGITAL JEDI
好的。 - Mukesh Soni
4个回答

0

db.transaction 是一个 异步 调用,有可能在执行 this.username = row.id 语句之前就调用了 UserInfo.username。不要直接访问 username,而是使用 promise 调用 UserInfo.getUserInfo() 并获取解析后的值,例如:

UserInfo.getUserInfo().then(username => {
    /* do whatever you want to do with username */
});

你需要在getUserInfo函数中进行以下更改:

getUserInfo = () => {
  return new Promise((resove, reject) => {
     db.transaction((tx) => {
        tx.executeSql('SELECT * FROM users', [], (tx, results) => {
            let row = results.rows.item(0);
            console.log("UserID: " + row.id) // return value from db, working
            this.username = row.id;

            resolve(this.username);

        }, (ts, err) => { 
            /* handle the failed case here */
            reject();
        });
    });
  }); 
}

希望这能有所帮助!


当调用 UserInfo.getUserInfo().then(...) 时,您将获得什么值? - Prasun
什么都没有显示,出现了错误。我之前是这样做的<Text>{UserInfo.username}</Text>。 - DIGITAL JEDI
但是现在我使用您上面的代码,它显示错误。 - DIGITAL JEDI
我尝试了这样做:UserInfo.getUserInfo().then(username => { /* 在这里进行你想要的操作 */ this.setState({username:username}) }); - DIGITAL JEDI
现在在render方法中,像这样做<Text>{this.state.username}</Text>,它应该可以工作。 - Prasun
显示剩余2条评论

0

我认为你可能正在失去“this”的范围

你能尝试以下方法并查看是否有效吗?

class UserInfo {
  constructor(props) {
    this.username = ""
    this.getUserInfo()
  }

  getUserInfo = () => {
    let ref = this; // save a reference to to this
    db.transaction((tx) => {
      tx.executeSql('SELECT * FROM users', [], (tx, results) => {
        let row = results.rows.item(0);
        console.log("UserID: " + row.id) // return value from db, working
        ref.username = row.id // save the username using the reference
      });
    });
  }

}

export default (new UserInfo())

你如何检查用户名是否为空?在代码中你在哪里使用它? - needsleep
我这样在另一个屏幕上调用它:UserInfo.username,但是它什么也没有显示。但是如果我手动设置this.username = "用户名",则在其他屏幕上会显示“用户名”。 - DIGITAL JEDI
如果你想在React组件中显示值,那么你应该使用一个继承自React.Component的类,并使用状态来更新你的UI。当你的UserInfo类初始化时,它的用户名被设置为空字符串。如果你此时尝试使用用户名,那么它将始终等于""。如果你稍后请求它,它将被正确更新。我认为你应该检查一下React组件的工作原理以及如何使用它们的状态。 - needsleep
我不想让它成为一个组件类,我只想让它成为一个基本类。 - DIGITAL JEDI
然后你应该自己处理UI的更新。这意味着当你实际上拥有用户名数据时,你需要使用新值通知其他组件。 - needsleep
因为你是手动设置的。你所拥有的getInfo函数是异步的,因此需要一些时间来更新值。这就是为什么它总是为空的原因。 - needsleep

0
您正在创建一个类UserInfo的新实例,此时您的用户名变量中存储的值为“空字符串”。如果您想在调用getUserInfo函数后从数据库获取值,则可以从函数返回该值,并在React组件中使用如下:
    class UserInfo {
    constructor(props) {
        this.username = ""
        this.getUserInfo
    }

    getUserInfo = () =>{
        return new Promise((resolve, reject) => { 
           db.transaction((tx) => {
             tx.executeSql('SELECT * FROM users', [], (tx, results) => {
                let row = results.rows.item(0);
                console.log("UserID: " + row.id) // return value from db, working
                // this.username = row.id
                resolve(row.id);
            });
           });
        })
    }
 }

export default (new UserInfo())

在从函数中返回值后,您可以在React组件中使用以下方式使用该值:

UserInfo.getUserInfo().then(username => {
     this.setState({username})
});

将这个值存储在您的状态中,在组件内部,您可以按如下方式使用它:

<Text>{this.state.username}</Text>

仍然是空的兄弟。 - DIGITAL JEDI
你能否通过控制台检查getUserInfo函数中then方法内的username值以及UserInfo类中row.id的值? - Akshay Rao
你的问题解决了吗?还是你还有其他问题? - Akshay Rao

0

你只需要保存App.js文件,然后重新启动Metro并重新加载R即可... 这对我很有效。 基本上,我认为我们需要专注于包装部分来解决这样的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接