Login
およびSignup
の反応ネイティブでfirebase authを使用したいのですが、黄色のエラーが発生しました:
タイマーを長時間、つまり複数分に設定することは、Androidでタイマーモジュールを起動したままにし、アプリが起動しているときのみタイマーを呼び出すことができるため、パフォーマンスと正確性の問題ですフォアグラウンド。詳細については、( https://github.com/facebook/react-native/issues/12981 )を参照してください。(持続時間111862msでsetTimeoutを見た)
それを修正する方法は?
それを無視したくありません。このエラーを理解し、最善かつ標準的な方法でそれを解決したいと思います。
そして、これが私のコードです。
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 Teamに報告しました:(- https://github.com/firebase/firebase-js-sdk/issues/97 )
GoogleのJosh Crowtherソフトウェアエンジニア:
ただし、マルチステップの短い期間のsetTimeoutsを使用しても、実際には問題は解決しません。タイマーモジュールは引き続きアクティブであり、アプリは警告に示されているパフォーマンスの問題の影響を受けます。ここでの問題は、長いタイマーを必要とするユースケースがあり、react-nativeはそのユースケースに対して最適化しないことです。
つまり、このバグはここでは修正できません。回避策がある場合にのみエラーを回避できます( 長時間、つまり数分間のタイマーの設定 )警告を無効にします。コード内の警告を無効にする作業を行っても、問題を解決できず(警告を無効にする以外)、完全に不要なSDKコード/重みが追加されます。
提供されている回避策に満足できない場合は、上記の問題(facebook/react-native#12981)に気をつけることをお勧めします
これにより、黄色のボックスとコンソールログが修正されます。 Expoでも修正されます。
コードベースの先頭に次のスクリプトを配置するだけです。
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);
}
};
私は同じ問題を抱えており、firebase web SDKの問題だと思うので、firebase web SDKはreact-nativeスレッドではなくjsスレッドで実行されるため、削除することにしました。
そして、私は react-native-firebase を見つけました。 Firebase Web SDKよりもパフォーマンスが優れているため、この問題はなくなりました
import { YellowBox } from 'react-native';
construct() {
YellowBox.ignoreWarnings(['Setting a timer']);
}
これは私にとっての警告を無視します。警告を表示するすべてのページのコンストラクタにこれを追加する必要があります。
これを無視するのは最善の方法ではありませんが、Firebase Realtime Databaseを使用している場合。 彼らは探している 問題が2年前であっても、ライブラリでこの問題を解決しようとしている。
login()
で、setTimeout()
呼び出しに間隔値がありません。一般に、ウィンドウ/タブがバックグラウンドにある場合、または少なくともタイムリーであるとは思われない場合、ブラウザはタイムアウト/間隔を起動しません。これは、不正なスクリプト動作を防ぎ、ポーリングしている可能性のあるスクリプトによる電力消費を削減するためです。
タイマーの実行中にユーザーがウィンドウから切り替えた場合、コードは原則として機能するはずです。 UXの観点からは、これはおそらくユーザーが望んでいることです。なぜなら、ユーザーは、見ているときにバックグラウンドで起こっているのではなく、遷移を見ているからです。メンタルコンテキストを維持するのに役立ちます。
黄色のボックスは、メッセージに応じて過度に長いタイマーを設定しているため(約2分)であり、それがコンテキスト的に必要なものになる可能性は低いためです。 JS環境は、あなたがやろうとしていることは意図したものではない可能性があることを警告しています。必要な場合は、警告をミュートできます。
別のアプローチは、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 too ..?
(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コールに対して、私はまだ1つの黄色いボックス警告(settimeoutで)を受け取りますが、それ以降の同時警告は決してありません。これを呼び出すだけで警告がトリガーされない可能性はありますが、Firebaseのasync
呼び出し後に並行警告がスローされることはありません。
Expoでは、関連するGithubの問題の CopyJoshの答え から取得したこのコードでのみ機能しました。
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
関数内にコードを配置することです。
同じ問題に直面しているようです。最短の方法は次のとおりです。
componentDidMount() { console.disableYellowBox = true; ... }
黄色の警告「タイマーの設定」に関する問題を回避します。
次のファイルをコピーしてインポートします(できるだけ早く;-))
import {Platform, InteractionManager} from 'react-native';
const _setTimeout = global.setTimeout;
const _clearTimeout = global.clearTimeout;
const MAX_TIMER_DURATION_MS = 60 * 1000;
if (Platform.OS === 'Android') {
// Work around issue `Setting a timer for long time`
// see: https://github.com/firebase/firebase-js-sdk/issues/97
const timerFix = {};
const runTask = (id, fn, ttl, args) => {
const waitingTime = ttl - Date.now();
if (waitingTime <= 1) {
InteractionManager.runAfterInteractions(() => {
if (!timerFix[id]) {
return;
}
delete timerFix[id];
fn(...args);
});
return;
}
const afterTime = Math.min(waitingTime, MAX_TIMER_DURATION_MS);
timerFix[id] = _setTimeout(() => runTask(id, fn, ttl, args), afterTime);
};
global.setTimeout = (fn, time, ...args) => {
if (MAX_TIMER_DURATION_MS < time) {
const ttl = Date.now() + time;
const id = '_lt_' + Object.keys(timerFix).length;
runTask(id, fn, ttl, args);
return id;
}
return _setTimeout(fn, time, ...args);
};
global.clearTimeout = id => {
if (typeof id === 'string' && id.startsWith('_lt_')) {
_clearTimeout(timerFix[id]);
delete timerFix[id];
return;
}
_clearTimeout(id);
};
}