React Router 的问题 - 页面在效果通过 api 调用响应设置状态之前渲染

问题描述 投票:0回答:1

我的 React 应用程序遇到了一个奇怪的问题。 这是一家模拟黑胶唱片店,现在我正在研究“以前的订单”功能。我正在 useEffect 块中向后端发送带有令牌的 GET 请求并设置订单状态。我通过上下文包装器获取令牌本身。 然后我的组件应该呈现结果。 代码如下:

import { useContext, useEffect, useState } from 'react'

import AuthContext from '../context/AuthContextProvider';

import { fetchAllOrders } from '../api/api';
import OrderDetails from './OrderDetails';


export const Orders = () => {
    const authCtx = useContext(AuthContext);
    const token = authCtx.loggedInUserData.auth_token
    const [orders, setOrders] = useState({});

    useEffect(() => {
        async function getAllOrders() {
            console.log("effect ran", token)
            const response = await fetchAllOrders(token);
            console.log(response)

            setOrders(response);
            // setOrders(response.data);       // when using axios
        }

        getAllOrders();
    }, [token]);

    console.log(orders)
    return (
        <main>
            {orders.length > 0 && { token } && <div>
                {orders.map(order =>
                    <OrderDetails key={order.id} order={order} />
                )}
            </div>
            }
        </main>
    )

}

令人费解的是,当我从应用程序本身访问该组件时,该组件按预期工作并呈现数据。 api 调用访问正确的端点,身份验证中间件成功传递,响应格式正确,最终显示在我的 FE 上。

但是,一旦我刷新选项卡或直接在地址栏中输入

http://localhost:3001/orders
,我就会收到 401 错误。

正如您所看到的,在第二个实例中,效果在获取令牌并将其发送到 api 之前运行,因此出现 401 响应。为什么会发生这种情况呢? 此外,在抛出错误之后,我似乎得到了预期的响应,但显然应用程序那时已经崩溃了。一旦我添加适当的错误处理,这可能不再是问题? 我根本不明白为什么应用程序在这两种情况下会有不同的行为。 顺便说一句,整个应用程序可以在这里找到,因为可能还有其他移动部件影响此功能。

reactjs async-await react-router react-context
1个回答
0
投票

获取数据没有任何条件,无论

token
值如何,都会进行获取。您可能希望修改效果以仅在存在定义的令牌值时发出获取请求。

此外,在渲染结果时,

{ token }
是一个对象,因此它always是真实的,使用just
token
来代替在以下情况下有条件地帮助结果:(a)有结果要渲染并且( b) 用于获取它们的真实令牌。

示例:

export const Orders = () => {
  const authCtx = useContext(AuthContext);
  const token = authCtx.loggedInUserData.auth_token;
  const [orders, setOrders] = useState({});

  useEffect(() => {
    async function getAllOrders() {
      const response = await fetchAllOrders(token);
      setOrders(response);
    }

    if (token) {
      getAllOrders(); // <-- only fetch orders if truthy token
    }
  }, [token]);

  return (
    <main>
      {!!orders.length && token && (
        <div>
          {orders.map(order =>
            <OrderDetails key={order.id} order={order} />
          )}
        </div>
      )}
    </main>
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.