我想有条件地在 Next.js 上呈现页面

Posted

技术标签:

【中文标题】我想有条件地在 Next.js 上呈现页面【英文标题】:I want to render the page on Next.js conditionally 【发布时间】:2021-06-04 16:48:37 【问题描述】:

我的 -app.js 上有以下代码:

  import  useState, useEffect  from "react";
  import PropTypes from "prop-types";
    
    ...


export default function MyApp(props) 
  const  Component, pageProps  = props;
  const [cartItems, setCartItems] = useState([]);

  //this prop will be passed to all the pages
  const passedProps = 
    ...pageProps,
    cartItems: cartItems,
    setCartItems: setCartItems,
  ;

  ...

    //on App load do the following:
      useEffect(() => 
       
    ...

    //get cart items from  localstorage if exist,else set to empty array;
    const savedCartItems = localStorage.getItem("cartItems"),
      cartItems = JSON.parse(savedCartItems) || [];
    setCartItems(cartItems);
  , []);

  return (
  
        ...
        <Component ...passedProps />
      ...
    </>
  );


MyApp.propTypes = 
  Component: PropTypes.elementType.isRequired,
  pageProps: PropTypes.object.isRequired,
;

以下是 checkout.js 上的代码

import  useEffect, useState  from "react";
import PropTypes from "prop-types";
import  useRouter  from "next/router";

...
export default function Checkout(props) 
     router = useRouter(),
     cartItems  = props;

 ...
  // on checkout page load if cart is empty redirect to carts page
  useEffect(() => 
    !cartItems.length && router.push("/cart");
  , [cartItems, router]);

 ...
  return (
   ...


Checkout.propTypes = 
  cartItems: PropTypes.arrayOf(
    PropTypes.shape(
      title: PropTypes.string,
      variations: PropTypes.objectOf(PropTypes.object),
      qty: PropTypes.number,
      price: PropTypes.number,
    )
  ),
;

仅当购物车为空时,我才需要从结帐页面重定向到购物车页面,但即使购物车中有商品,我每次都会被重定向。我认为这是因为在初始页面加载时,项目仍未从本地存储加载到父应用程序组件并且仍未定义。有什么解决办法吗??

【问题讨论】:

那么您是否希望重定向仅在页面加载时发生?如果有人稍后在页面上向卡片添加项目,它不应该重定向吗? 结帐是一个单独的页面。如果购物车中没有商品,结帐应立即重定向。假设有人在 url 中键入以下地址:localhost/checkout。现在如果购物车是空的,他应该被重定向到购物车页面。你明白我的意思了吗?? 你的路由器是否响应路由器 dom? 没有它的“下一个/路由器”。 它不是路由器问题,它的发生是因为使用效果,由于 next.js 中的 s-s-r,我必须在 useEffect 中重定向。问题是一开始没有从本地存储中加载项目并且购物车是空的。 【参考方案1】:

您的问题是因为您使用长度为 0 的空数组初始化 cartItems,因此始终执行:

!cartItems.length && router.push("/cart");

相反,将其初始化为不带值:

const [cartItems, setCartItems] = useState();

并将 useEffect 更改为:

  // on page Load,if cart is empty redirect to carts page
  useEffect(() => 
    if (Array.isArray(cartItems) && cartItems.length === 0) 
      router.push("/cart");
    
  , [cartItems, router]);
      

这样,重定向只会在以下情况下执行:

    cartItems 已在父项中设置 不为空。

【讨论】:

!cartItems.length 将在非空数组上返回 false 并且不应执行。仅当长度值为 0 时才会执行。因为零是虚假的,大于零是真实的。我之前尝试过。问题不在于初始化,而在于将项目从本地存储加载到父级。我已经试过你的答案了。 developer.mozilla.org/en-US/docs/Glossary/Falsy null 和 undefined 也是虚假的。所以当用于条件语句时,零等于 null 或 undefined 我明白什么是虚假值。总是执行,我的意思是在初始反应渲染时,状态用一个空数组初始化,所以检查返回 true。然后从本地存储中获取项目的父级中的 useEffect 发生,它更新状态,但此时重定向已经发生。如果你说你已经尝试过了,但它不起作用,那么你能发一个minimal, reproducible example吗? 没问题,falsy 正是我使用Array.isArray 来明确检查localStorage 操作是否已经发生而不是!carsItems.length 的原因,因为即使您初始化为空。 抱歉,这是我的错误,已编辑修复!

以上是关于我想有条件地在 Next.js 上呈现页面的主要内容,如果未能解决你的问题,请参考以下文章

React 组件道具未在 Next.js 页面中呈现

Next.js 中奇怪的命令式 onScroll 路由行为(仅在服务器上呈现)

在 Next.js 中为 styled-jsx 动态添加样式

带有 useEffect 的 Next.js useRouter 即使在页面刷新时满足条件也会推送

Next.js 将 NODE_ENV 传递给客户端

Next.js:如何在特定页面上更改根 div __next 的 css?