【问题标题】:React Native reuse function that sets state设置状态的 React Native 重用函数
【发布时间】:2019-02-23 22:21:18
【问题描述】:

我是 React Native 的新手。在我的应用程序中,用于检查用户是否存在于数据库中的相同功能用于 3 个不同的文件。

checkUserExists = (userId) => {
        var that = this;
        database.ref('users').child(userId).once('value').then(function(result){
        const exists = (result.val() !== null);

        if (exists) {
            var data = result.val();
            that.setState({
                username: data.username,
                name: data.name
            })
        }
    })
}

为了减少代码量,我想把这个函数放到一个组件中,以便它可以被重用。所以我用这个函数创建了一个新文件:

export function checkUserExists (userId) {
    database.ref('users').child(userId).once('value').then(function(result){
        const exists = (result.val() !== null);

        if (exists) {
            var data = result.val();
            setState({
                username: data.username,
                name: data.name
            })
        }
    })
}

但这遇到了[未处理的承诺拒绝:ReferenceError:找不到变量:setState]

处理这个问题的正确方法是什么?我必须使用 Redux 吗?到目前为止,我找不到关于 SO 的明确答案。

更新:我也试过了

export default class Authentication extends Component {
    checkUserExists = (userId) => {
        database.ref('users').child(userId).once('value').then(function(result){
            const exists = (result.val() !== null);

            if (exists) {
                var data = result.val();
                setState({
                    username: data.username,
                    name: data.name
                })
            }
        })
    }
}

我试着这样称呼它

Authentication.checkUserExists(user.id);

但得到:TypeError: _authentication.default.checkUserExists 不是函数

【问题讨论】:

    标签: reactjs react-native redux react-redux setstate


    【解决方案1】:

    你可以做两件事来让它发挥作用

    1. 将.then函数改为箭头函数或绑定
    2. 调用 checkUserExists 函数,在其中使用类上下文执行它
     export function checkUserExists (userId) {
            database.ref('users').child(userId).once('value').then((result) => {
                const exists = (result.val() !== null);
    
                if (exists) {
                    var data = result.val();
                    this.setState({
                        username: data.username,
                        name: data.name
                    })
                }
            })
        }
    

    现在你想在哪里使用 checkUserExists,你可以将它与 .call 一起使用

    checkUserExists.call(this, userId);
    

    不过,此解决方案的一个缺点是可能难以调试您的应用,因为状态是通过组件外部的代码设置的

    要克服缺点,您可以定义您的方法,例如

    export async function checkUserExists (userId) {
          try {
            const result = await database.ref('users').child(userId).once('value');
            const exists = (result.val() !== null);
            if (exists) {
                return data;
            }
            return false;
          } catch(e) {
             console.log(e);
    
          }
      }
    

    并在组件中像使用它一样

    someFunc = async () => {
       const data = await checkUserExists(userId);
       if (data) {
            this.setState({
                username: data.username,
                name: data.name
            })
       }
    }
    

    【讨论】:

    • 第一种方法是我在组件本身中执行 setState 的唯一方法吗?第二种方法将数据传回给调用者。我对function.call()格式不是很熟悉
    • @JacobMarsellos,是的,第一种方法是在组件之外执行 setState 的唯一方法。您可以阅读有关.call here 的其他方法可能对您很方便的另一种方法是 .apply 和 .bind 您可以检查它们之间的区别here
    • 正如你提到的,我想避免潜在的困难调试。所以第二个解决方案似乎更好。但是,第二种解决方案仍然会强制在不同的文件中重复代码,因为回调总是相同的,对吧?
    • 确实第二种解决方案应该是可行的方法,但它仍然有一点冗余
    【解决方案2】:

    您需要在组件内调用this.setState。你不能只是从任何地方打电话。

    您的辅助函数未绑定到您的类。注意在原来的var that = this 中设置了that.setState 将在then 块内工作。在您的原始示例中,checkUserExists 很可能是使用 https://github.com/tc39/proposal-class-fields 绑定的。现在您有了一个常规(未绑定到类)函数,它无法访问this 或其任何方法,包括setState。

    老实说,这是一个 XY 问题,恕我直言。如果你想提取一个辅助函数,你应该让它返回你需要的数据,而不是试图传递对你想要更新其状态的类的引用。相反,您应该只将数据返回给组件——而且您必须这样做,因为您的数据库调用无论如何都是异步的——并在组件中使用该数据来调用它自己的 setState 方法。

    https://reactjs.org/docs/react-component.html#setstate

    【讨论】:

    • 更新了我的答案。其他人的帖子中的所有内容也都是正确的,并且解决了有关绑定的相同问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-23
    • 2021-12-18
    • 1970-01-01
    • 2021-06-03
    • 1970-01-01
    相关资源
    最近更新 更多