Javascript 太多的重新渲染。React限制渲染的数量以防止无限循环。使用上下文API传递参数
我正在使用React context获取登录函数和错误,该函数和错误在上下文提供程序文件中定义,用于登录firebase数据库,并使用登录中抛出的错误在应用程序中显示 我的问题是,当我只是使用firebase身份验证抛出的错误在应用程序中显示错误时,我没有收到任何错误,但我还添加了其他错误,如空字段,以便在应用程序中也显示错误字段 在这样做之后,我得到了太多的重新渲染错误。我认为这个错误是由于在函数中使用了多个if语句造成的。你能建议一个新的选择吗?如果这是错误的,请解释 上下文提供程序文件Javascript 太多的重新渲染。React限制渲染的数量以防止无限循环。使用上下文API传递参数,javascript,reactjs,react-native,react-hooks,context-api,Javascript,Reactjs,React Native,React Hooks,Context Api,我正在使用React context获取登录函数和错误,该函数和错误在上下文提供程序文件中定义,用于登录firebase数据库,并使用登录中抛出的错误在应用程序中显示 我的问题是,当我只是使用firebase身份验证抛出的错误在应用程序中显示错误时,我没有收到任何错误,但我还添加了其他错误,如空字段,以便在应用程序中也显示错误字段 在这样做之后,我得到了太多的重新渲染错误。我认为这个错误是由于在函数中使用了多个if语句造成的。你能建议一个新的选择吗?如果这是错误的,请解释 上下文提供程序文件 i
import React from 'react';
import auth from '@react-native-firebase/auth';
export const AuthContext = React.createContext();
export const AuthProvider = ({children}) => {
const [user, setUser] = React.useState(null);
const [error, setError] = React.useState('');
return (
<AuthContext.Provider
value={{
user,
setUser,
error,
login: async (email, pwd) => {
try {
await auth().signInWithEmailAndPassword(email, pwd);
} catch (e) {
setError(e);
}
},
register: async (email, pwd) => {
try {
await auth().createUserWithEmailAndPassword(email, pwd);
} catch (e) {
setError(e);
}
},
logout: async () => {
try {
await auth().signOut();
} catch (e) {
console.log(e);
}
},
}}>
{children}
</AuthContext.Provider>
);
};
import React from 'react';
import {Button, Image, Text, TouchableOpacity, View} from 'react-native';
import styles from '../styles/Styles';
import FormInput from '../components/FormInput';
import FormButton from '../components/FormButton';
import SocialButton from '../components/SocialButton';
import {AuthContext} from '../navigation/AuthProvider';
import ErrorText from '../components/ErrorText';
const LoginScreen = ({navigation}) => {
const [email, setEmail] = React.useState('');
const [password, setPassword] = React.useState('');
const {login, error} = React.useContext(AuthContext);
const [errorForwarded, setErrorForwarded] = React.useState(null);
if (error) {
setErrorForwarded(error);
}
if (!email || !password) {
setErrorForwarded('fields-empty');
}
const renderErrorText = e => {
if (e.code === 'auth/invalid-email') {
return <ErrorText errorText="Email invalid!" />;
}
if (e.code === 'auth/user-not-found') {
return <ErrorText errorText="User not found!" />;
}
if (e.code === 'auth/wrong-password') {
return <ErrorText errorText="Wrong password!" />;
}
if (e === 'fields-empty') {
return <ErrorText errorText="Fields cannot be empty!" />;
}
};
return (
<View style={styles.loginContainer}>
<Image
source={require('../assets/rn-social-logo.png')}
style={styles.loginLogo}
/>
<Text style={styles.loginText}>Sign In</Text>
<FormInput
labelValue={email}
onChangeText={email => setEmail(email)}
placeholderText="Email"
iconType="user"
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
/>
<FormInput
labelValue={password}
onChangeText={pwd => setPassword(pwd)}
placeholderText="Password"
iconType="lock"
secureTextEntry={true}
/>
{error ? renderErrorText(errorForwarded) : null}
<FormButton
buttonTitle="Sign In"
onPress={() => {
{
email && password ? login(email, password) : {};
}
}}
/>
<TouchableOpacity style={styles.loginForgetBtn}>
<Text style={styles.loginNavBtnText}>Forgot Password?</Text>
</TouchableOpacity>
<SocialButton
buttonTitle="Sign In with Facebook"
buttonType="facebook-square"
color="#4867aa"
backgroundColor="#e6eaf4"
/>
<SocialButton
buttonTitle="Sign In with Google"
buttonType="google"
color="#de4d41"
backgroundColor="#f5e7ea"
/>
<TouchableOpacity
style={styles.loginForgetBtn}
onPress={() => navigation.navigate('Signup')}>
<Text style={styles.loginNavBtnText}>
Don't have an account? Create here...
</Text>
</TouchableOpacity>
</View>
);
};
export default LoginScreen;
从“React”导入React;
从'@react native firebase/auth'导入身份验证;
export const AuthContext=React.createContext();
导出常量AuthProvider=({children})=>{
const[user,setUser]=React.useState(null);
const[error,setError]=React.useState(“”);
返回(
{
试一试{
等待auth()。使用email和Password进行登录(电子邮件,pwd);
}捕获(e){
设置错误(e);
}
},
注册:异步(电子邮件,pwd)=>{
试一试{
等待auth().createUserWithEmailAndPassword(电子邮件,pwd);
}捕获(e){
设置错误(e);
}
},
注销:异步()=>{
试一试{
等待身份验证()。注销();
}捕获(e){
控制台日志(e);
}
},
}}>
{儿童}
);
};
应用程序文件
import React from 'react';
import auth from '@react-native-firebase/auth';
export const AuthContext = React.createContext();
export const AuthProvider = ({children}) => {
const [user, setUser] = React.useState(null);
const [error, setError] = React.useState('');
return (
<AuthContext.Provider
value={{
user,
setUser,
error,
login: async (email, pwd) => {
try {
await auth().signInWithEmailAndPassword(email, pwd);
} catch (e) {
setError(e);
}
},
register: async (email, pwd) => {
try {
await auth().createUserWithEmailAndPassword(email, pwd);
} catch (e) {
setError(e);
}
},
logout: async () => {
try {
await auth().signOut();
} catch (e) {
console.log(e);
}
},
}}>
{children}
</AuthContext.Provider>
);
};
import React from 'react';
import {Button, Image, Text, TouchableOpacity, View} from 'react-native';
import styles from '../styles/Styles';
import FormInput from '../components/FormInput';
import FormButton from '../components/FormButton';
import SocialButton from '../components/SocialButton';
import {AuthContext} from '../navigation/AuthProvider';
import ErrorText from '../components/ErrorText';
const LoginScreen = ({navigation}) => {
const [email, setEmail] = React.useState('');
const [password, setPassword] = React.useState('');
const {login, error} = React.useContext(AuthContext);
const [errorForwarded, setErrorForwarded] = React.useState(null);
if (error) {
setErrorForwarded(error);
}
if (!email || !password) {
setErrorForwarded('fields-empty');
}
const renderErrorText = e => {
if (e.code === 'auth/invalid-email') {
return <ErrorText errorText="Email invalid!" />;
}
if (e.code === 'auth/user-not-found') {
return <ErrorText errorText="User not found!" />;
}
if (e.code === 'auth/wrong-password') {
return <ErrorText errorText="Wrong password!" />;
}
if (e === 'fields-empty') {
return <ErrorText errorText="Fields cannot be empty!" />;
}
};
return (
<View style={styles.loginContainer}>
<Image
source={require('../assets/rn-social-logo.png')}
style={styles.loginLogo}
/>
<Text style={styles.loginText}>Sign In</Text>
<FormInput
labelValue={email}
onChangeText={email => setEmail(email)}
placeholderText="Email"
iconType="user"
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
/>
<FormInput
labelValue={password}
onChangeText={pwd => setPassword(pwd)}
placeholderText="Password"
iconType="lock"
secureTextEntry={true}
/>
{error ? renderErrorText(errorForwarded) : null}
<FormButton
buttonTitle="Sign In"
onPress={() => {
{
email && password ? login(email, password) : {};
}
}}
/>
<TouchableOpacity style={styles.loginForgetBtn}>
<Text style={styles.loginNavBtnText}>Forgot Password?</Text>
</TouchableOpacity>
<SocialButton
buttonTitle="Sign In with Facebook"
buttonType="facebook-square"
color="#4867aa"
backgroundColor="#e6eaf4"
/>
<SocialButton
buttonTitle="Sign In with Google"
buttonType="google"
color="#de4d41"
backgroundColor="#f5e7ea"
/>
<TouchableOpacity
style={styles.loginForgetBtn}
onPress={() => navigation.navigate('Signup')}>
<Text style={styles.loginNavBtnText}>
Don't have an account? Create here...
</Text>
</TouchableOpacity>
</View>
);
};
export default LoginScreen;
从“React”导入React;
从“react native”导入{按钮、图像、文本、TouchableOpacity、视图};
从“../styles/styles”导入样式;
从“../components/FormInput”导入FormInput;
从“../components/FormButton”导入FormButton;
从“../components/SocialButton”导入SocialButton;
从“../navigation/AuthProvider”导入{AuthContext};
从“../components/ErrorText”导入ErrorText;
const LoginScreen=({navigation})=>{
const[email,setEmail]=React.useState(“”);
const[password,setPassword]=React.useState(“”);
const{login,error}=React.useContext(AuthContext);
常量[errorForwarded,setErrorForwarded]=React.useState(null);
如果(错误){
setErrorForwarded(错误);
}
如果(!电子邮件| |!密码){
setErrorForwarded('fields-empty');
}
const renderErrorText=e=>{
如果(e.code==='auth/invalid email'){
返回;
}
如果(e.code==='auth/user not found'){
返回;
}
如果(e.code==='auth/密码错误'){
返回;
}
如果(e==‘字段为空’){
返回;
}
};
返回(
登录
设置电子邮件(电子邮件)}
占位符text=“电子邮件”
iconType=“用户”
keyboardType=“电子邮件地址”
autoCapitalize=“无”
自动更正={false}
/>
设置密码(pwd)}
占位符text=“密码”
iconType=“锁定”
secureTextEntry={true}
/>
{错误?renderErrorText(errorForwarded):null}
{
{
电子邮件和密码?登录(电子邮件,密码):{};
}
}}
/>
忘记密码了?
导航。导航('Signup')}>
没有帐户?在这里创建。。。
);
};
导出默认登录屏幕;
这里是无限循环
返回true并更新状态您的if语句
- 更新状态将重新加载程序组件
- 重新加载组件再次执行您的if指令
- 无限循环
constloginscreen=({navigation})=>{
const[email,setEmail]=React.useState(“”);//此空值
const[password,setPassword]=React.useState(“”);//此空值
//条件将直接在此处运行它直接在LoginScreen下运行
如果(!email | |!password){//则返回true,因为email和password是空值
//此处的更新状态将重新加载组件并再次执行此条件
setErrorForwarded('fields-empty');
}
为了避免这种情况
const onSubmit=()=>{
如果(!电子邮件| |!密码){
setErrorForwarded('fields-empty');
}否则{
//在这里调用api
}
}
调用Submit on button subimt press您遇到多个重新渲染器的原因与函数中的if条件无关。通过运行函数直接在组件的函数中设置状态,您正在强制重新渲染器,然后它开始从上到下运行函数,然后再次从上到下运行该函数设置状态 只有react钩子不会重新初始化/运行,并且可以防止在每个后续的重新渲染器上运行,因此您需要使用
useffect()
钩子和一系列依赖项来监视,这样您就不会在重新渲染器上运行不必要的状态更改
我将包括对代码相关位的更改(在App组件的return语句之前)
谢谢大家,我知道导致重新渲染的问题是函数组件中直接存在多个if语句,我就是不知道如何克服这个问题 当我使用一个函数来检查那些if条件来设置那些状态,并在调用API之前在button submit中调用该函数时,它起到了作用。但我认为useEffect钩子做得更好,谢谢大家对我的解释 我可以澄清一些其他的事情吗,比如说,起初错误变量为空,所以errorForwarded将设置为空。现在在重新渲染时,errorForwarded将设置为空。所以我的问题是,即使检测到状态更改,实际状态值也没有更改。那么为什么要重新渲染。谢谢。将您的
如果(错误)
和如果(!电子邮件| |)!