【问题标题】:State undefined in reduxredux 中的状态未定义
【发布时间】:2021-12-27 14:15:01
【问题描述】:

我正在使用最新的 react 版本 6.0.2 我正在关注 lama dev youtube 视频,以使用 react 制作购物网站。 我想将状态(使用 redux)及其数据传递到成功页面,然后使用“购物车”及其“产品”及其所有信息来进一步保存订单。 在视频中,这是使用“useHistory()”方法完成的,我正在使用 useNavigate()(这适用于 React 路由器 dom v6)。我正在努力进一步解析数据以获取显示为空的所需购物车和产品。我得到了状态,但购物车和产品在开发工具的 Redux 状态下显示为空。

我的成功页面是这样的

const Success = () => {
    const location = useLocation();
    console.log(location); // to see what state are being passed after placing an order

    const data = location.state;
    const cart = location.state.cart;
    console.log(data, cart);
    const currentUser = useSelector((state) => state.user.currentUser);

    const [orderId, setOrderId] = useState(null);

    useEffect(() => {
        const createOrder = async () => {
            try {
                const res = await userRequest.post("/orders", {
                    userId: currentUser._id,
                    products: cart.products.map((item) => ({
                        productId: item._id,
                        quantity: item.quantity,
                    })),
                    amount: cart.total,
                    address: data.billing_details.address,
                });
                setOrderId(res.data._id);
            } catch (err) {
                console.log(err);
            }
        };

        data && createOrder();
    }, [cart, data, currentUser]);

    return (
        <Container>
            {orderId
                ? `Order has been created successfully. Your order number is ${orderId}`
                : `????Successfull. Your order is being prepared...`}
            <Link to="/">
                <Button>Go to Homepage</Button>
            </Link>
        </Container>
    );
};

export default Success;

我的购物车页面如下所示

const Cart = () => {
    const cart = useSelector((state) => state.cart);
    const [stripeToken, setStripeToken] = useState(null);
    // const history = useNavigate();
    const navigate = useNavigate();

    const onToken = (token) => {
        setStripeToken(token);
    };

    //token returns on successful order placing
    console.log(stripeToken);

    useEffect(() => {
        const makeRequest = async () => {
            try {
                const res = await userRequest.post("/checkout/payment", {
                    tokenId: stripeToken.id,
                    amount: cart.total * 100,
                });

                navigate("/success", { state: res, cart });
            } catch (err) {
                console.log(err);
            }
        };
        stripeToken && makeRequest();
    }, [stripeToken, cart.total, navigate]);

    return (
        <Container>
            <Navbar />
            <Announcement />

            <Wrapper>
                <Title>YOUR BAG</Title>
                <Top>
                    <TopBotton>CONTINUE SHOPPING</TopBotton>
                    <TopTexts>
                        <TopText>
                            <ShoppingBag
                                style={{ margin: '-3px 2px', color: 'teal' }}
                            />{' '}
                            BAG(3)
                        </TopText>
                        <TopText>
                            <Favorite
                                style={{ margin: '-3px 2px', color: 'red' }}
                            />{' '}
                            WISHLIST(0)
                        </TopText>
                    </TopTexts>
                    <TopBotton type="filled">CHECKOUT NOW</TopBotton>
                </Top>
                <Bottom>
                    <Info>
                        {cart.products.map((product) => (
                            <Product>
                                <ProductDetail>
                                    <Image src={product.img} />
                                    <Details>
                                        <ProductName>
                                            <b>Product:</b> {product.title}
                                        </ProductName>
                                        <ProductId>
                                            <b>ID:</b> {product._id}
                                        </ProductId>
                                        <ProductColor color={product.color} />
                                        <ProductSize>
                                            <b>Size:</b> {product.size}
                                        </ProductSize>
                                    </Details>
                                </ProductDetail>
                                <PriceDetail>
                                    <Hr />
                                    <ProductAmountContainer>
                                        <Add />
                                        <ProductAmount>
                                            {product.quantity}
                                        </ProductAmount>
                                        <Remove />
                                    </ProductAmountContainer>
                                    <ProductPrice>
                                        ₹ {product.price * product.quantity}
                                    </ProductPrice>
                                </PriceDetail>
                            </Product>
                        ))}
                        <Hr />

                        {/* <Product>
                                <ProductDetail>
                                    <Image src="https://images.pexels.com/photos/9558241/pexels-photo-9558241.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"/>
                                    <Details>
                                        <ProductName><b>Product:</b> HAKURA T-SHIRT</ProductName>
                                        <ProductId><b>ID:</b> 124541</ProductId>
                                        <ProductColor color="grey"/>
                                        <ProductSize><b>Size:</b> M</ProductSize>
                                    </Details>
                                </ProductDetail>
                                <PriceDetail>
                                    <Hr/>
                                    <ProductAmountContainer>
                                        <Add/>
                                        <ProductAmount>2</ProductAmount>
                                        <Remove/>
                                    </ProductAmountContainer>
                                    <ProductPrice>$ 30</ProductPrice>
                                </PriceDetail>
                            </Product> */}
                    </Info>

                    <Summary>
                        <SummaryTitle>ORDER SUMMARY</SummaryTitle>

                        <SummaryItem>
                            <SummaryItemText>Subtotal: </SummaryItemText>
                            <SummaryItemPrice>₹ {cart.total}</SummaryItemPrice>
                        </SummaryItem>

                        <SummaryItem>
                            <SummaryItemText>
                                Estimated Shipping:{' '}
                            </SummaryItemText>
                            <SummaryItemPrice>₹ 150.90</SummaryItemPrice>
                        </SummaryItem>

                        <SummaryItem>
                            <SummaryItemText>
                                Shipping Discount:{' '}
                            </SummaryItemText>
                            <SummaryItemPrice>-₹ 150.90</SummaryItemPrice>
                        </SummaryItem>
                        <Hr />
                        <SummaryItem type="total">
                            <SummaryItemText>Total: </SummaryItemText>
                            <SummaryItemPrice>₹ {cart.total}</SummaryItemPrice>
                        </SummaryItem>

                        <StripeCheckout
                            name="Ecofelx"
                            image="https://avatars.githubusercontent.com/Ardent10"
                            billingAddress
                            shippingAddress
                            description={`Your total is ₹ ${cart.total}`}
                            currency="INR"
                            amount={cart.total * 100}
                            token={onToken}
                            stripeKey={KEY}
                        >
                            <Button>CHECKOUT NOW</Button>
                        </StripeCheckout>
                    </Summary>
                </Bottom>
            </Wrapper>

            <Footer />
        </Container>
    );
};

export default Cart;

这里看一下redux截图。我想要购物车、它的产品并获取它们各自的 ID,以便我可以在后端下订单并运送到它的地址。 Redux screenshot

编辑:我更新的方法 我意识到 cart.jsx 中的 useSelector() 用于获取状态购物车,然后该购物车在成功页面上传递,该页面进一步用于下订单。我再次使用 useSelector() 成功地在那里抓住了购物车,而不是通过导航。

//我的购物车.jsx

 const cart = useSelector((state)=>state.cart);
    const [stripeToken, setStripeToken] = useState(null);
    // const history = useNavigate();
    const navigate = useNavigate();

    const onToken = (token) =>{
        setStripeToken(token);
    }

    //token returns on successful order placing
    // console.log(stripeToken); 

    useEffect(() => {
        const makeRequest = async () => {
          try {
            const res = await userRequest.post("/checkout/payment", {
              tokenId: stripeToken.id,
              amount: 500,
            });

            navigate("/success", {state:res});
          } 
          catch(err)
          {
              console.log(err);
          }
        };
        stripeToken && makeRequest();
      }, [stripeToken, cart.total , navigate]);

// 我的success.jsx 页面现在

const location = useLocation();
    // console.log(location); // to see what state are being passed after placing an order

    const cart = useSelector((state)=>state.cart);
    const data = location.state;
    console.log(data,cart);

   

 

    const currentUser = useSelector((state)=>state.user.currentUser);

    const [orderId, setOrderId] = useState(null);
    console.log(orderId);

    useEffect(() => {
    
        const createOrder = async () => {
            try {
              const res = await userRequest.post("/orders", {
              
                  userId: currentUser._id,
                  products: cart.products.map((item) => ({
                    productId: item._id,
                    quantity: item.quantity,
                })),
                amount: cart.total,
                address: data.billing_details.address,
              });
              setOrderId(res.data._id);
            } 
            catch(err) {
                console.log(err);  
          }
        };

        data && createOrder();
      }, [cart, data, currentUser]);


      return (
        <Container>
          {orderId
            ? `????Order has been created successfully. Your order number is ${orderId}`
            : `????Successfull. Your order is being prepared...`}
          <Link to="/">
            <Button>Go to Homepage</Button>
          </Link>
        </Container>
      );
    };
    

结果截图-> result console

【问题讨论】:

  • 除了通过路由状态将cart 状态传递到成功页面之外,您的 redux 状态与发送路由状态有什么关系尚不清楚。你能澄清你的问题/问题的这一部分吗?
  • 发送数据和购物车的原因是当成功页面显示给用户时,后端需要将产品的所有详细信息和下订单的用户发送到订单路线,以便成功下订单。我将数据发布到订单路线。我是 react 和 redux 的新手,这是我的第一个项目。这是 [1:21:00] 的视频 youtube.com/watch?v=y66RgYMAgSo 是我的主要问题所在。该视频是在 react-router-dom 5.3.0 上制作的,我使用的是 6.0.2。
  • 感谢您的宝贵时间。我是初学者,我尝试使用您的答案来实现,但我的 redux 开发工具显示 mw 选择的购物车和产品,但在我的 cart.jsx 页面数据和购物车和未定义中。我现在坚持了3天。还是谢谢你。
  • 我从 youtube 视频中看不到您的问题。正如我在回答中建议的那样,他们甚至将状态传递为data。问题是您的Success 组件没有看到正确的路由状态吗?您正在使用函数组件和 React 钩子,所以我看不出在这方面 react-router-dom 版本之间会有多大差异。你能分享一个更完整的代码示例吗?你是如何声明路线的?你能为我们提供足够的背景来重现这个问题吗?您能否将您的代码分叉到一个 running 代码框中,以便我们可以实时检查和调试?
  • 是的,我可以看到在我的 MongoDB 集合中放置的相应订单,您介意在我完成这个项目之前问您更多疑问吗?有一些我想自定义的功能在视频中没有完成。

标签: javascript reactjs redux react-router


【解决方案1】:

您只发送一个处于路由状态的res 对象,缺少的是cart 状态。

const res = await userRequest.post("/checkout/payment", {
  tokenId: stripeToken.id,
  amount: cart.total * 100,
});

navigate(
  "/success",
  {
    state: res, // <-- only res sent in route state
    cart,
  },
);

路由状态应该是一个对象,all是你想要传递的状态。

const data = await userRequest.post("/checkout/payment", {
  tokenId: stripeToken.id,
  amount: cart.total * 100,
});

navigate(
  "/success",
  {
    state: {
      data, 
      cart,
    },
  },
);

从成功页面中的路由状态正确解构两者。

const { state } = useLocation();
console.log({ state });

const { data, cart } = state || {};

console.log({ data, cart });

【讨论】:

    猜你喜欢
    • 2016-12-22
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 2021-12-09
    • 2019-04-07
    • 1970-01-01
    • 2018-09-20
    • 2021-10-07
    相关资源
    最近更新 更多