React native不会使用所有新状态重新渲染

如何解决React native不会使用所有新状态重新渲染

我正在建立注册表,但遇到了问题。用户填写完字段后,我用正则表达式进行验证检查。每个验证功能都会设置一条错误消息。即使我故意触发了所有这些错误,但如果我提交表单,则只会出现一个错误。这是我的代码:

function RegisterScreen(): JSX.Element{


    const pwInput = React.createRef();
    const [firstName,setFirstName] = useState('');
    const [lastName,setLastName] = useState('');
    const [email,setEmail] = useState('');
    const [password,setPassword] = useState('');
    const [confirmPassword,setConfirmPassword] = useState('');
    const [birthday,setBirthday] = useState<Date | null>(null);
    const [isSelected,setSelection] = useState(false); 
    const [openTerms,setOpenTerms] = useState(false);
    const [emailError,setEmailError] = useState<string | null>(null);
    const [passError,setPassError] = useState<string | null>(null);
    const [confPassError,setConfPassError] = useState<string | null>(null);
    const [isTermsChecked,setIsTermsChecked] = useState<string | null>(null); 
   

    function _validateEmail(): boolean{
        const re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        if(re.test(email))
            return true;
        else{
            setEmailError(RegisterErrors.emailError);
            return false;
        }
       
    }
    function _validatePw(): boolean{
        const re = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/
        
        if(re.test(password)) return true;
        else{
            setPassError(RegisterErrors.pwWeak);
            return false
        }
    }
    function _pwMatch(): boolean{

        if(password == confirmPassword){
            
            return true;
        }else{
            setConfPassError(RegisterErrors.pwConfirmMatchError);
            return false;
        }
    }

    function _validateAge(): boolean{
            return true;
    }

    function _validateTermsAndCond(): boolean{
            return true;
    } 

   

    function validateFieldsAndRegister(){

        console.log(email);
        console.log(password);
        console.log(confirmPassword);
        
        if( _validateEmail() && _validatePw() && _validateAge() && _validateTermsAndCond() && _pwMatch()){

                //trimite la firebase
                console.log("okay")

        }else{

           console.log('wrong fields')

            
        }

    }


  return(
        <SafeAreaView style={{flex:1}}>
     
        <ScrollView>
        <View style = {{flex:1,alignItems: "center",justifyContent:"center",backgroundColor:"white"}}>
        
        <TermsAndConditions open = {openTerms} close = { ()=>setOpenTerms(false) }/>
    
        <Image source={require("../../images/logoR.png")} style={styles.logoImg}/>
        

        <Text style={styles.mainText}>Register</Text>
        


        
          <Input  
            containerStyle={styles.inputView}
            inputContainerStyle={{backgroundColor:"white"}}
            placeholder="First Name..." 
            placeholderTextColor="rgb(0,0)"
            errorStyle={{ color: 'red' }}
            onChangeText={text => setFirstName(text)}/>
        
      
          <Input  
            containerStyle={styles.inputView}
            placeholder="Last Name..." 
            placeholderTextColor="rgb(0,0)"
            errorStyle={{ color: 'red' }}
            onChangeText={text => setLastName(text)}/>
        
       
        
          <Input 
            onFocus={()=>{setPassError(null)}}
            
            secureTextEntry
            containerStyle={styles.inputView}
            placeholder="Password..." 
            placeholderTextColor="rgb(0,0)" 
            errorStyle={{ color: 'red' }}
            errorMessage={passError}
            onChangeText={text =>setPassword(text)}/>
       

      
          <Input  
            secureTextEntry
            onFocus = {()=>{setConfPassError(null)}}
            containerStyle={styles.inputView}
            placeholder="Confirm Password..." 
            placeholderTextColor="rgb(0,0)"
            errorStyle={{ color: 'red' }}
            errorMessage={confPassError}
            
            onChangeText={text =>setConfirmPassword(text)}/>
      

       
          <Input  
            containerStyle={styles.inputView}
            onFocus={()=>{setEmailError(null)}}
            placeholder="Email..." 
            placeholderTextColor="rgb(0,0)"
            errorStyle={{ color: 'red' }}
            errorMessage={emailError}
            
            onChangeText={text => setEmail(text)}/>
       

         
        <View style={styles.checkboxContainer}>
            <CheckBox
            value={isSelected}
            onValueChange={()=>{setSelection(!isSelected)}}
            style={styles.checkbox}
          
            />
    
            <TouchableOpacity onPress = {()=> {setOpenTerms(true);}}>
            <Text style={styles.label}>Terms and Conditions</Text>
            </TouchableOpacity>

        </View>

        <TouchableOpacity  style={{...styles.inputView,...styles.regBtnContainer}} onPress = {()=>{validateFieldsAndRegister()}}>
            <Text style = {styles.txtRegBtn}>Register</Text>
        </TouchableOpacity>
        

        </View>
        
</ScrollView>

</SafeAreaView>
    )
}

Screenshot

如果我在validateFieldsAndRegister的if语句之前调用验证功能,它将起作用。错误将显示在3个字段中。

这是我显示的错误

export const RegisterErrors = {

    emailError: "You must enter a valid email",pwConfirmMatchError:"The passwords you entered are not the same",termsAndCondError:"You must read and agree with the Terms and Conditions",birthdayError:"You must be 21 or older",pwWeak:"Your password must contain: a lowercase letter,a acapital letter,a number and minimum 8 characters"

}

解决方法

以下是说明正在发生的事情的摘要。它说明了三种更新状态的策略。

第一个将所有三个setState()调用分组为一个函数调用,并且不使用if()语句检查结果。状态更改会立即显示。

第二个命令将更新分为三个分别调用async函数的调用,这些函数依次调用await一个超时函数,然后再调用setState()。这些调用是在OP从if()语句中进行时进行的。每个异步函数都返回一个Promise,该Promise被评估为“真”,并且我们看到“ promise”已记录到控制台。超时结果然后滴入。

第三种情况最接近OP的问题。它还从if()语句中进行单独的调用,但它们是同步的并返回false。第一个调用完成了它的setState()调用,返回false并从if内部停止进一步的调用。由于状态已更改,React调用了渲染,因此我们看到了单个状态更改。

所有这一切的结果是,最好是在if()语句之前进行验证调用,或者更好的是,收集所有验证结果,然后将所有setState()调用分组为一个。单一功能。这将使React可以更有效地对这些更改进行分组,并调用尽可能少的渲染器。

(抱歉,代码段混乱,内置的babel似乎无法处理async/await

.container {
  display: flex;
  
}
.example {
  margin: 1rem;
  padding: 1rem;
  border: 1px solid gray;
}
button {
  margin: 1rem;
}
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/babel">
  const { useState } = React
  
  function App() {
  const [stateOne,setStateOne] = useState(1);
  const [stateTwo,setStateTwo] = useState(1);
  const [stateThree,setStateThree] = useState(1);
  
  const cycleStateSingle = () => {
    setStateOne((state) => state + 1);
    setStateTwo((state) => state + 1);
    setStateThree((state) => state + 1);
  }
  
  const [stateOnePromise,setStateOnePromise] = useState(1);
  const [stateTwoPromise,setStateTwoPromise] = useState(1);
  const [stateThreePromise,setStateThreePromise] = useState(1);
  
  const cycleOne = async () => {
      await new Promise(resolve => setTimeout(resolve,1000));
      setStateOnePromise((state) => state + 1);
  }
  
  const cycleTwo = async () =>{
      await new Promise(resolve => setTimeout(resolve,2000));
      setStateTwoPromise((state) => state + 1);
  }
  
  const cycleThree = async () =>{
      await new Promise(resolve => setTimeout(resolve,3000));
      setStateThreePromise((state) => state + 1);
  }
  
  const cycleStatePromise = () => {
    if (cycleOne(true) && cycleTwo(true) && cycleThree(true)) {
      console.log('promise');
    }
  }
  
  const [stateOneStepped,setStateOneStepped] = useState(1);
  const [stateTwoStepped,setStateTwoStepped] = useState(1);
  const [stateThreeStepped,setStateThreeStepped] = useState(1);
  
  const cycleOneStepped = () => {
      setStateOneStepped((state) => state + 1);
      return false;
  }
  
  const cycleTwoStepped = () =>{
      setStateTwoStepped((state) => state + 1);
      return false;
  }
  
  const cycleThreeStepped = () =>{
    setStateThreeStepped((state) => state + 1);
    return false;
  }
  
  const cycleStateStepped = () => {
    if (cycleOneStepped() && cycleTwoStepped() && cycleThreeStepped()) {
      console.log('stepped');
    }
  }
  
  return (
  <div className="container">
    <div className="example">
      <div className="state-1">State 1: {stateOne}</div>
      <div className="state-2">State 2: {stateTwo}</div>
      <div className="state-3">State 3: {stateThree}</div>
      <button type="button" onClick={cycleStateSingle}>Single State Change</button>
    </div>
    <div className="example">
      <div className="state-1">State 1: {stateOnePromise}</div>
      <div className="state-2">State 2: {stateTwoPromise}</div>
      <div className="state-3">State 3: {stateThreePromise}</div>
      <button type="button" onClick={cycleStatePromise}>Promise State Change</button>
    </div>
    <div className="example">
      <div className="state-1">State 1: {stateOneStepped}</div>
      <div className="state-2">State 2: {stateTwoStepped}</div>
      <div className="state-3">State 3: {stateThreeStepped}</div>
      <button type="button" onClick={cycleStateStepped}>Stepped State Change</button>
    </div>
    </div>
  );
}

ReactDOM.render(<App />,document.getElementById('root'));
</script>

<div id="root"></div>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-