设置状态的 React Native 重用函数

React Native reuse function that sets state

我是 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 不是函数

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

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

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

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

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

  1. 将.then函数改成箭头函数或绑定
  2. 在 class 上下文中调用 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
        })
   }
}