React Native:“渲染的钩子比预期的要少。”不知道这意味着啥,应用程序崩溃?

Posted

技术标签:

【中文标题】React Native:“渲染的钩子比预期的要少。”不知道这意味着啥,应用程序崩溃?【英文标题】:React Native: "Rendered fewer hooks than expected." No clue what this means, app crashes?React Native:“渲染的钩子比预期的要少。”不知道这意味着什么,应用程序崩溃? 【发布时间】:2021-07-19 20:47:33 【问题描述】:

我有一个 AuthScreen 应该处理所有的登录、注册、忘记密码等逻辑。代码如下:

import React,  useState  from 'react';
import  RootStateOrAny, useDispatch, useSelector  from "react-redux";
import  authForgotPassword, authLogin, authRegister  from '../store/actions/authActions';

import ForgotPassword from '../components/Auth/ForgotPassword';
import Login from '../components/Auth/Login';
import PageType from '../utils/PageType';
import Register from '../components/Auth/Register';
import  StackNavigationProp  from '@react-navigation/stack';

type ParamList = 
    AuthLoadingScreen: undefined;
    HomeTabScreen: undefined;
    AuthScreen: undefined


type AuthScreenNavigationProp = StackNavigationProp<ParamList, 'AuthScreen'>;

type Props = 
    navigation: AuthScreenNavigationProp;


export default function AuthScreen( navigation : Props) 
    const dispatch = useDispatch();
    const user = useSelector((state: RootStateOrAny) => state.auth.user);
    
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [password2, setPassword2] = useState('');

    const [showPage, setShowPage] = useState(PageType.Login);

    const changePage = (pageType: PageType) => 
        setEmail('');
        setPassword('');
        setPassword2('');
        setShowPage(pageType);
    

    const login = () => 
        dispatch(authLogin(email, password));
    

    const register = () => 
        if (password === password2) 
            dispatch(authRegister(email, password));
         else 
            alert('Passwords must match!');
        
    

    const forgotPassword = () => 
        dispatch(authForgotPassword(email, changePage));
    

    if (user) 
        navigation.navigate('HomeTabScreen');
        return null;
     else 
        switch(showPage) 
            case PageType.Login: 
                return Login(email, setEmail, password, setPassword, changePage, login);
            
            case PageType.Register: 
                return Register(email, setEmail, password, setPassword, password2, setPassword2, changePage, register);
            
            case PageType.ForgotPassword: 
                return ForgotPassword(email, setEmail, changePage, forgotPassword);
            
            default: return Login(email, setEmail, password, setPassword, changePage, login);
        
    

我有组件“登录”、“注册”和“忘记密码”,每个组件都显示(返回)不同的布局、操作等。

所以我制作了一个钩子和一个开关盒,例如在“登录”组件中按下“在此处注册”时,它将使用 REGISTER 页面值调用“changePage”。它应该重新渲染“AuthScreen”,看到“showPage”值更改为“REGISTER”,然后再次进入我的 switch-case,并返回“REGISTER”值。无论如何,这就是我的想法。

尝试设置 showPage 挂钩“setShowPage(pageType);”时发生错误在“changePage”功能中。如果我对此发表评论,应用不会崩溃,但也不会更改页面。

这是什么意思,我该如何修复我的屏幕?

【问题讨论】:

我认为它与您从 switch 语句返回组件的方式有关。 与你的问题无关,你考虑过使用 react-router 吗? @im_baby 不,您也可以将它与 react-native 一起使用吗?我也尝试过查看嵌套导航器,为我的加载页面、身份验证页面、主页等创建一个切换导航器,然后为我的身份验证页面本身创建另一个导航器(登录、注册、忘记密码),但是当尝试导航到主页,它说该导航器下不存在页面:s React-router 可以在原生 reactrouter.com/native 中使用。但正如另一位用户所建议的那样,react-navigation 可能也很合适。 【参考方案1】:

虽然我建议为此使用react-navigation,但问题似乎在于您返回组件并将道具传递给它们的方式,例如Login(email, setEmail, password, setPassword, changePage, login)应该是&lt;Login email=email setEmail=setEmail password=password setPassword=setPassword changePage=changePage login=login/&gt;

import React,  useState  from 'react';
import  RootStateOrAny, useDispatch, useSelector  from "react-redux";
import  authForgotPassword, authLogin, authRegister  from '../store/actions/authActions';

import ForgotPassword from '../components/Auth/ForgotPassword';
import Login from '../components/Auth/Login';
import PageType from '../utils/PageType';
import Register from '../components/Auth/Register';
import  StackNavigationProp  from '@react-navigation/stack';

type ParamList = 
    AuthLoadingScreen: undefined;
    HomeTabScreen: undefined;
    AuthScreen: undefined


type AuthScreenNavigationProp = StackNavigationProp<ParamList, 'AuthScreen'>;

type Props = 
    navigation: AuthScreenNavigationProp;


export default function AuthScreen( navigation : Props) 
    const dispatch = useDispatch();
    const user = useSelector((state: RootStateOrAny) => state.auth.user);
    
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [password2, setPassword2] = useState('');

    const [showPage, setShowPage] = useState(PageType.Login);

    const changePage = (pageType: PageType) => 
        setEmail('');
        setPassword('');
        setPassword2('');
        setShowPage(pageType);
    

    const login = () => 
        dispatch(authLogin(email, password));
    

    const register = () => 
        if (password === password2) 
            dispatch(authRegister(email, password));
         else 
            alert('Passwords must match!');
        
    

    const forgotPassword = () => 
        dispatch(authForgotPassword(email, changePage));
    

    if (user) 
        navigation.navigate('HomeTabScreen');
        return null;
     else 
        switch(showPage) 
            case PageType.Login: 
                return <Login email=email setEmail=setEmail password=password setPassword=setPassword changePage=changePage login=login/>
            
            case PageType.Register: 
                return <Register email=email setEmail=setEmail password=password setPassword=setPassword password2=password2 setPassword2=setPassword2 changePage=changePage register=register/>
            
            case PageType.ForgotPassword: 
                return <ForgotPassword email=email setEmail=setEmail changePage=changePage forgotPassword=forgotPassword/>
            
            default: return <Login email=email setEmail=setEmail password=password setPassword=setPassword changePage=changePage login=login/>
        
    

【讨论】:

如果你必须这样做,你会怎么做?使用反应导航? 你应该问另一个问题,如果这个答案能解决你的问题,我也可以回答。 React Native 上的导航也有点复杂,因为 Tabs 和 Drawers 是不同的。 当然!我一直在盲目地盯着它,但是我怎么可能忽略了这么简单的事情……如果可以的话,我会问另一个问题并在其中标记您:) 我在这里提出了一个新问题:***.com/questions/67268327/…【参考方案2】:

据我了解,登录/注册/忘记密码是功能组件。那些应该像

一样返回
return <Login email=email setEmail=setEmail ... />

而不仅仅是像现在这样的普通函数调用:

return Login(email, setEmail)

如果你没有使用 jsx/tsx,那么你应该这样称呼它:

React.createElement(Login,  email, setEmail, ... , ...children)

但一般来说,你为什么不直接使用 React Router 并为 Login、Register、ForgotPassword 等添加一个单独的 &lt;Route /&gt; 而不是这个组件?那将是一个更优雅的解决方案。

【讨论】:

但是当然...?!!叹了口气,我一直盯着自己看,我怎么可能忽略了哈哈? 发生在我们最好的人身上。 :)

以上是关于React Native:“渲染的钩子比预期的要少。”不知道这意味着啥,应用程序崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

渲染的钩子比预期的要少。这可能是由于意外提前退货声明造成的。基于状态的条件渲染组件

react-native init 指定 react 版本和 react-native 版本

添加 React-Native-Camera 和 React-Native-Push-Notification 后无法构建 React Native

react native 增加react-native-camera

更新 react-native-maps 以使用 create-react-native-app

react native 增加react-native-storage