【问题标题】:useEffect is not firing after router.push in Next.js在 Next.js 中的 router.push 之后,useEffect 没有触发
【发布时间】:2021-11-28 06:22:51
【问题描述】:

从 login.jsx 提交登录后,用户将导航到 index.jsx,并使用 router.push('/')。 这两个文件(更具体的页面)都位于 /pages 目录下的根目录中。并且所有页面都会自动将 Layout.jsx 作为布局。布局文件有 Nav.jsx 组件。在 Nav.jsx 中,注册了一个 useEffect 钩子,但问题是:在 router.push('/') 之后它永远不会触发我在钩子内尝试了 console.log() 但没有运气。但是,当重新加载页面或将router.push('/') 替换为window.location.replace('/') 时,它会执行挂钩。这是我的代码:

login.jsx:

... (previous code)
            axios.post(`/auth/login`, loginForm).then((res) => {
            const {data, token} = res.data;

            localStorage.setItem('auth_token', token);
            localStorage.setItem('user', JSON.stringify(data));

            router.push('/');
... (next code)

布局.jsx:

import Head from 'next/head'
import Nav from "./Nav";

export default function Layout({children}) {
    return (
        <>
            <Head>
                <title>Super site!</title>
                <link rel="icon" href={"/favicon.ico"}/>
            </Head>
            <header>
                <Nav/>
            </header>
            <main>{children}</main>
            <footer>
                <h1>Super site footer</h1>
            </footer>
        </>
    )
}

Nav.jsx:

export default function Nav() {
    const router = useRouter();
    const [user, setUser] = useState(null);

    const logout = (e) => {
        e.preventDefault();

        axios.post(`/auth/logout`).then(() => {
            localStorage.removeItem('auth_token');
            localStorage.removeItem('user');

            router.replace('/');
            router.reload();
        }).catch((err) => {
            if (err.response) {
                toast.error(err.response.data.message, toasterOptions('error'));
            } else {
                toast.error(getServerErrorMessage(), toasterOptions('error'));
            }
        });
    }

    useEffect(() => {
        console.log('hi');
        const storedUser = JSON.parse(localStorage.getItem('user'));

        if (storedUser) setUser(storedUser);
    }, []);

    return (
        <>
            <nav className={'sm-nav'}>
                <input type="checkbox" name="menu-btn" id="menu-btn" className={'hidden menu-btn'}/>
                <ul className={'header-ul'}>
                    <li>
                        <Link href="/">
                            <a className={'logo'}>Devlanceer</a>
                        </Link>
                    </li>
                    <li>
                        <label htmlFor="menu-btn" className={'menu-icon bars'}>
                            <FontAwesomeIcon icon={"bars"} className={'md:hidden cursor-pointer'} size={'lg'}/>
                        </label>
                        <label htmlFor="menu-btn" className={'menu-icon times hidden'}>
                            <FontAwesomeIcon icon={"times"} className={'cursor-pointer'} size={'lg'}/>
                        </label>
                    </li>
                </ul>
                <ul className={'dropmenu'}>
                    {
                        user && (
                            <li>
                                <a onClick={logout} className={'pointered'}>Logout</a>
                            </li>
                        )
                    }
                    {
                        !user && (
                            <>
                                <li>
                                    <Link href={'/login'}>
                                        <a>Login</a>
                                    </Link>
                                </li>
                                <li>
                                    <Link href={'/register'}>
                                        <a>Create account</a>
                                    </Link>
                                </li>
                            </>
                        )
                    }
                </ul>
                <Toaster/>
            </nav>
            <nav className={'md-nav'}>
                <ul>
                    <li>
                        <Link href="/">
                            <a className={'logo'}>Super App</a>
                        </Link>
                    </li>
                </ul>
                <ul className={'block md:flex'}>
                    {
                        user && (
                            <li>
                                <a onClick={logout} className={'pointered'}>Logout</a>
                            </li>
                        )
                    }
                    {
                        !user && (
                            <>
                                <li>
                                    <Link href={'/login'}>
                                        <a className={'btn rounded-full'}>Login</a>
                                    </Link>
                                </li>
                                <li>
                                    <Link href={'/register'}>
                                        <a className={'btn rounded-full btn-primary'}>Create account</a>
                                    </Link>
                                </li>
                            </>
                        )
                    }
                </ul>
            </nav>
        </>
    )
}

我该如何解决这个问题?我希望在 Nav.jsx 组件上执行 useEffect() 钩子。

【问题讨论】:

    标签: reactjs next.js


    【解决方案1】:

    如果你将你的位置写入钩子会发生什么?来自documentation

    如果你想运行一个效果并只清理一次(在挂载和 unmount),您可以传递一个空数组 ([]) 作为第二个参数。

    useEffect(() => {
        console.log('hi');
        const storedUser = JSON.parse(localStorage.getItem('user'));
    
        if (storedUser) setUser(storedUser);
    },[router.pathname]); // re-run the effect if your location changes, router.pathname or wherever your router stores the current location
    

    【讨论】:

      猜你喜欢
      • 2019-07-06
      • 2021-07-22
      • 1970-01-01
      • 2022-01-26
      • 2013-11-04
      • 2011-07-26
      • 2019-08-06
      • 1970-01-01
      • 2021-02-16
      相关资源
      最近更新 更多