Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/448.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 太多的重新渲染。React限制渲染的数量以防止无限循环。使用上下文API传递参数_Javascript_Reactjs_React Native_React Hooks_Context Api - Fatal编程技术网

Javascript 太多的重新渲染。React限制渲染的数量以防止无限循环。使用上下文API传递参数

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

我正在使用React context获取登录函数和错误,该函数和错误在上下文提供程序文件中定义,用于登录firebase数据库,并使用登录中抛出的错误在应用程序中显示

我的问题是,当我只是使用firebase身份验证抛出的错误在应用程序中显示错误时,我没有收到任何错误,但我还添加了其他错误,如空字段,以便在应用程序中也显示错误字段

在这样做之后,我得到了太多的重新渲染错误。我认为这个错误是由于在函数中使用了多个if语句造成的。你能建议一个新的选择吗?如果这是错误的,请解释

上下文提供程序文件

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')}>
没有帐户?在这里创建。。。
);
};
导出默认登录屏幕;
这里是无限循环

  • 您的if语句
    返回true并更新状态
  • 更新状态将重新加载程序组件
  • 重新加载组件再次执行您的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将设置为空。所以我的问题是,即使检测到状态更改,实际状态值也没有更改。那么为什么要重新渲染。谢谢。

将您的
如果(错误)
如果(!电子邮件| |)!