【问题标题】: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 可能也很合适。

标签: reactjs react-native react-hooks jsx


【解决方案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 是不同的。
  • 当然!我一直在盲目地盯着它,但是我怎么可能忽略了这么简单的事情……如果可以的话,我会问另一个问题并在其中标记您:)
  • 我在这里提出了一个新问题:stackoverflow.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; 而不是这个组件?那将是一个更优雅的解决方案。

【讨论】:

  • 但是当然...?!!叹了口气,我一直盯着自己看,我怎么可能忽略了哈哈?
  • 发生在我们最好的人身上。 :)
猜你喜欢
  • 2022-06-13
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
  • 2021-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-10
相关资源
最近更新 更多