我想使用firebase auth with {native Login
和Signup
,但我收到黄色错误:
长时间(即多分钟)设置计时器是Android上的性能和正确性问题,因为它使计时器模块保持唤醒状态,并且只有在应用程序位于前台时才能调用计时器。有关详细信息,请参阅(https://github.com/facebook/react-native/issues/12981)。 (看到setTimeout,持续时间为111862ms)
我该如何解决?
我不想忽视这一点,我想理解这个错误并用最好的标准方式解决这个问题
这是我的代码:
export default class Login extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
password: '',
response: ''
}
this.signUp = this.signUp.bind(this)
this.login = this.login.bind(this)
}
async signUp() {
try {
await firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
this.setState({
response: 'Account Created!'
})
setTimeout(() => {
this.props.navigator.push({
id: 'App'
})
}, 1500)
} catch (error) {
this.setState({
response: error.toString()
})
}
}
async login() {
try {
await firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
this.setState({
response: 'user login in'
})
setTimeout(() => {
this.props.navigator.push({
id: 'App'
})
})
} catch (error) {
this.setState({
response: error.toString()
})
}
}
render() {
return (
<View style={styles.container}>
<View style={styles.containerInputes}>
<TextInput
placeholderTextColor="gray"
placeholder="Email"
style={styles.inputText}
// onChangeText={(email) => this.setState({ email })}
onChangeText={(email) => {console.log(email);}}
/>
<TextInput
placeholderTextColor="gray"
placeholder="Password"
style={styles.inputText}
password={true}
onChangeText={(password) => this.setState({ password })}
/>
</View>
<TouchableHighlight
onPress={this.login}
style={[styles.loginButton, styles.button]}
>
<Text
style={styles.textButton}
>Login</Text>
</TouchableHighlight>
<TouchableHighlight
onPress={this.signUp}
style={[styles.loginButton, styles.button]}
>
<Text
style={styles.textButton}
>Signup</Text>
</TouchableHighlight>
</View>
)
}
}
我向 Google Firebase小组报告:(https://github.com/firebase/firebase-js-sdk/issues/97)
答案 0 :(得分:9)
这会修复黄色框和控制台日志。它甚至为世博会确定了它。
只需将以下脚本放在代码库的开头即可。
import { YellowBox } from 'react-native';
import _ from 'lodash';
YellowBox.ignoreWarnings(['Setting a timer']);
const _console = _.clone(console);
console.warn = message => {
if (message.indexOf('Setting a timer') <= -1) {
_console.warn(message);
}
};
答案 1 :(得分:6)
Google Say的Josh Crowther软件工程师:
使用多步短持续时间setTimeouts实际上并没有解决问题。定时器模块仍然保持活动状态,应用程序仍然会受到警告中指示的性能问题的影响。这里的问题是,我们的用例需要很长的计时器,而本地的反应并没有针对该用例进行优化。
所有这一切的网络:此错误无法解决,我们只能解决错误,有可用的解决方法(请参阅Setting a timer for a long period of time, i.e. multiple minutes)禁用警告。在我们的代码中执行禁用警告的工作,不会帮助解决问题(除了禁用警告之外),并添加完全没有必要的额外SDK代码/权重。
如果您对提供的解决方法感到不舒服,我建议您解决上述问题(即facebook / react-native#12981)
答案 2 :(得分:3)
如果您使用的是 react-native 0.63
,请在您的 App.js
文件中执行以下操作:
从 react-native
LogBox
import { LogBox } from 'react-native';
并且在您的 App.js
文件中的所有导入之后只添加这一行,没有必要在任何 useEffect 调用中添加这一行。
LogBox.ignoreLogs(['Setting a timer for a long period of time'])
请参阅 docs 了解更多信息。
如果您使用的是 react-native 0.62
,请在您的 App.js
文件中执行以下操作:
从 react-native
YellowBox
import { YellowBox } from 'react-native';
并且在您的 App.js
文件中的所有导入之后只添加这一行,没有必要在任何 useEffect 调用中添加这一行。
YellowBox.ignoreWarnings(['Setting a timer for a long period of time']);
请参阅 docs 了解更多信息。
答案 3 :(得分:3)
我所做的并且正在与我一起工作,但是不管是否是一种好的做法,我仍然不知道
导航到文件
node_modules \ react-native \ Libraries \ Core \ Timers \ JSTimers.js
有一个函数const MAX_TIMER_DURATION_MS = 60 * 1000
,我将时间增加为60 * 100000,它停止出现了
答案 4 :(得分:2)
我遇到了同样的问题,我认为这是firebase web SDK的问题所以我决定放弃firebase web SDK,因为它运行在js线程中,而不是反应原生线程。
我找到了react-native-firebase。它比具有更高性能的firebase web SDK更好,这个问题消失了
答案 5 :(得分:2)
只需添加这两行
import { LogBox } from 'react-native';
LogBox.ignoreLogs(['Setting a timer']);
答案 6 :(得分:2)
我正在使用此代码禁用警告
import { YellowBox } from 'react-native';
YellowBox.ignoreWarnings(['Setting a timer']);
答案 7 :(得分:2)
对于Firebase / firestore用户:我没有尝试掩盖/隐藏警告,而是简单地恢复为REST API。就像魅力一样:)
firebase
节点软件包进行身份验证atob
和bto
黑客)下面的代码段仅使用HTTP客户端(https://github.com/hardcodet/httpclient-js),您可以使用任何适合自己的功能(例如fetch或axios)。
// Firebase App (the core Firebase SDK) is always required and
// must be listed before other Firebase SDKs
import * as firebase from "firebase/app";
import "firebase/auth";
import {LoginStatus} from "./LoginStatus";
import {auth, User} from "firebase";
import {ApiResponse, DelegateBearerAuthClient, HttpClient} from "@hardcodet/httpclient";
import {Env} from "../../Env";
export class FirebaseClient {
/**
* Creates a simple API client to use with Firestore.
* We don't want to use the JS package's implementation since it has issues with
* long-running timers - see https://github.com/firebase/firebase-js-sdk/issues/97
* @param idToken The user's ID token as retrieved through firebase auth
*/
private static getFirestoreClient(idToken: string) {
const projectId = Env.firebaseProjectId;
const baseUri = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default)/documents/`
const authClient = new DelegateBearerAuthClient(async () => idToken);
return new HttpClient(baseUri, {authClient});
}
/**
* Use firebase auth for login etc. because lazy.
*/
public static async userLogin(email: string, password: string): Promise<User> {
try {
const credentials: firebase.auth.UserCredential = await auth().signInWithEmailAndPassword(email, password);
return credentials.user;
} catch (error) {
console.error(error);
return undefined;
}
}
private static resolveStatus(errorCode: string): { user: User, status: LoginStatus } {
switch (errorCode) {
case "auth/invalid-email":
return {user: undefined, status: LoginStatus.InvalidEmailAddress};
case "auth/user-not-found":
return {user: undefined, status: LoginStatus.UnknownUserId};
case "auth/wrong-password":
return {user: undefined, status: LoginStatus.WrongPassword};
case "auth/email-already-in-use":
return {user: undefined, status: LoginStatus.EmailAddressAlreadyInUse};
case "auth/weak-password":
return {user: undefined, status: LoginStatus.WeakPassword};
case "auth/user-disabled":
return {user: undefined, status: LoginStatus.UserDisabled};
case "auth/expired-action-code":
return {user: undefined, status: LoginStatus.InvalidActionCode};
default:
return {user: undefined, status: LoginStatus.Undefined};
}
}
/**
* Resolve the user's keys from the backend.
*/
public static async getSomeUserData(firebaseUserId: string, idToken: string): Promise<...> {
const client: HttpClient = FirebaseClient.getFirestoreClient(idToken);
// userData here is the name of my collection in firestore. i'm using the user ID as the document ID
var result = await client.getAs<any>(`userData/${firebaseUserId}?key=${Env.firebaseApiKey}`);
if (result.success) {
const json = result.value;
const foo = json.fields.foo.stringValue;
const bar = json.fields.bar.stringValue;
return ...
} else {
if (result.notFound) {
// that document with that key doesn't exist
console.warn("no document with key " + firebaseUserId);
return undefined;
}
throw result.createError();
}
}
public static async writeSomeData(idToken: string, firebaseUserId: string, foo: string, bar: string): Promise<...> {
const data = {
"fields": {
"foo": {
"stringValue": foo
},
"bar": {
"stringValue": bar
}
}
};
// again, just do an HTTP post, use the firebase user ID as the document key
const client: HttpClient = FirebaseClient.getFirestoreClient(idToken);
const result: ApiResponse = await client.post(`userData?documentId=${firebaseUserId}&key=${Env.firebaseApiKey}`, data);
if (result.success) {
return ...
} else {
throw result.createError();
}
}
/**
* Gets the currently logged in user, if any.
*/
public static getCurrentUser(): User {
return auth().currentUser;
}
public static async sendPasswordReset(email: string): Promise<LoginStatus> {
try {
await auth().sendPasswordResetEmail(email);
return LoginStatus.Success;
} catch (error) {
return FirebaseClient.resolveStatus(error.code).status;
}
}
/**
* Clears the current user from the session.
*/
public static async signOut() {
await auth().signOut();
}
}
请注意idToken
参数-这只是您从firebase User
类中获得的ID令牌:
const user: User = await FirebaseClient.userLogin("me@domain.com", "mypassword");
const idToken= await user.getIdToken(false);
const data = await FirebaseClient.getSomeUserData(user.uid, idToken);
答案 8 :(得分:1)
另一种方法是使用react-native-ignore-warnings模块。
https://github.com/jamrizzi/react-native-ignore-warnings
https://www.npmjs.com/package/react-native-ignore-warnings
这甚至适用于Expo应用程序。
您可以通过以下方式使用它。 。
import ignoreWarnings from 'react-native-ignore-warnings';
ignoreWarnings('Setting a timer');
也可以用android运行..?
答案 9 :(得分:1)
在login()
中,您的setTimeout()
来电缺少间隔值。作为一般情况,如果窗口/选项卡在后台,或者至少不期望它们是及时的,浏览器现在不会触发超时/间隔。这是为了防止滥用脚本行为,并减少可能轮询的脚本的功耗。
您的代码原则上应该工作,如果用户在计时器运行时切换窗口,它将在返回时完成。从UX的角度来看,这可能是您想要的,因为用户看到了转换,而不是在他们不看时在后台发生。它有助于他们保持心理背景。
黄色框是因为您根据消息(将近两分钟)设置了一个过长的计时器,并且这不太可能是您想要的上下文。 JS环境警告你,你正在做的事情不太可能是你想要的。如果符合您的要求,您可以将警告静音。
答案 10 :(得分:1)
我认为最有效的解决方案(直到RN内部修复)是here中提到的解决方案。
// add this code to your project to reset all timeouts
const highestTimeoutId = setTimeout(() => ';');
for (let i = 0; i < highestTimeoutId; i++) {
clearTimeout(i);
}
习惯了-针对Firebase调用,我仍然收到一个黄框警告(在settimeout上),但是此后再也不会出现任何并发警告。我不确定在此时调用此方法可能也不会触发唯一的警告,但是在Firebase的async
调用之后不会再引发任何并发警告。
答案 11 :(得分:1)
要解决此问题...
导航到您的node_modules / react-native / Libraries / Core / Timers / JSTimers.js文件。
寻找变量MAX_TIMER_DURATION_MS
将其值更改为10000 * 1000
保存更改(关闭自动格式)并重新构建您的应用。
在https://github.com/firebase/firebase-js-sdk/issues/97#issuecomment-485410026
上找到了这个答案答案 12 :(得分:0)
这将忽略所有警告。
App.js
import { LogBox} from "react-native";
....
LogBox.ignoreAllLogs();
答案 13 :(得分:0)
在Expo中,它仅对我有用,该代码是我在相关的Github问题中从CopyJosh's answer获得的:
class App extends Component {
constructor() {
super();
YellowBox.ignoreWarnings(['Setting a timer']);
console.ignoredYellowBox = ['Setting a timer'];
const consoleClone = clone(console);
console.warn = message => {
if (message.indexOf('Setting a timer') <= -1) {
consoleClone.warn(message);
}
};
}
render() {
return (...);
}
}
export default App;
关键是将代码放在App
入口点constructor
函数中。
答案 14 :(得分:0)
面对同样的问题。似乎,我们暂时不得不隐藏警告。这是最简单的方法:
componentDidMount() { console.disableYellowBox = true; ... }
答案 15 :(得分:0)
解决带有黄色警告“设置计时器”的问题。
(尽可能快地复制并导入以下文件;-))
void OnTriggerStay2D(Collider2D other)
{
if (Input.GetKeyDown(interactableKey))
{
chestInventoryUI.SetActive(true);
Time.timeScale = 0.0f;
}
if (Input.GetKeyUp(interactableKey))
{
chestInventoryUI.SetActive(false);
Time.timeScale = 1.0f;
}
}
答案 16 :(得分:0)
import { YellowBox } from 'react-native';
construct() {
YellowBox.ignoreWarnings(['Setting a timer']);
}
这忽略了对我的警告。您应该将其添加到显示警告的每个页面的构造函数中。
忽略它不是最好的方法,但是如果您使用的是Firebase Realtime Database。 They are looking与其图书馆一起解决此问题,即使该问题已有2年之久了。