0

我是新来的反应和做一个项目。我正在构建一个包含 3 个卡片组件的页面。他们都使用反应查询和 Axios 来获取数据。我的页面有时可以工作,但总是随机向我抛出有关未定义属性“地图”的错误。我在 useState 挂钩中使用空数组作为初始状态,但有时我仍然会收到此错误。无法弄清楚为什么会这样。

这是我的卡片组件的代码。我还有另外两张代码相似的卡。

import React,{useState} from "react";
import {Card, Spin, Divider, List, Tag} from 'antd';
import axiosInstance from "../axios";
import {  useQuery } from 'react-query';

const { Meta } = Card;



const MyPlantMatrix=()=> {
const[myPlantMatrix,setMyPlantMatrix] = useState([]);
const {status, data, error, isFetching} = useQuery('myplantmatrix', async ()=>{
    const {data} = await axiosInstance.get("api_url/?format=json");
    console.log(data);
    setMyPlantMatrix(data);
    return data;
})
    const renderedPlantMatrix = myPlantMatrix.map(
        plants => {
            return <Card style = {{ width:400}} key={plants}>
                <Meta title="My Assigned Plants"></Meta>
                <Divider/>
                 {plants.assigned_plant_code.map(
                     plantcode => {
                         return <Tag>{plantcode}</Tag>
                     }
                 ) }

            </Card>
        }
    )

    return(
        <div>
            {status === 'loading' ? (
                <Spin/>
            ): status === 'error' ? (
                error.message
            ):(
                <>
                    {renderedPlantMatrix}
                    <div>{
                        isFetching ? 'Data is updating in background...' : ''
                    }</div>
                </>
            )}
            
        </div>

    );
}

export default MyPlantMatrix;

这是我调用上述组件进行渲染的页面的代码。

import React, {useState,useEffect} from "react";
import { List,Card } from 'antd';

import MyBuyerProfile from "../../components/MyBuyerProfile";
import MyAssignedPlants from "../../components/MyPlantMatrix";
import MyMarketMatrix from "../../components/MyMarketMatrix";
const gridStyle = {
    width: '25%',
    textAlign: 'center',
};

function MyAccountView() {

        return (
            <Card title="My Profile">
                <List
                    grid={{
                        gutter: 16,
                        xs: 1,
                        sm: 2,
                        md: 4,
                        lg: 4,
                        xl: 6,
                        xxl: 3,
                    }}>
                    <List.Item>
                        <MyBuyerProfile/>
                    </List.Item>
                    <List.Item>
                        <MyAssignedPlants/>
                    </List.Item>
                    <List.Item>
                        <MyMarketMatrix/>
                    </List.Item>
                </List>
            </Card>
        );

}

export default MyAccountView;

这是我添加 Auth 标头的 Axios 实例的代码。我不断收到警报错误“发生服务器/网络错误看起来可能是 CORS 问题。对此很抱歉 - 我们会尽快修复它。” 有时当我刷新。我无法弄清楚为什么会触发它。

// import React from "react";
import axios from 'axios';
// import { Alert } from 'antd';
const baseURL = MyBaseURL;

const axiosInstance = axios.create({
    baseURL: baseURL,
    timeout: 5000,
    headers: {
        Authorization: localStorage.getItem('access_token')
            ? 'Bearer ' + localStorage.getItem('access_token')
            : null,
        'Content-Type': 'application/json',
        accept: 'application/json',
    },
});

axiosInstance.interceptors.response.use(
    (response) => {
        return response;
    },
    async function (error) {
        const originalRequest = error.config;

        if (typeof error.response === 'undefined') {
            alert(
                'A server/network error occurred. ' +
                'Looks like CORS might be the problem. ' +
                'Sorry about this - we will get it fixed shortly.'
            );

            return Promise.reject(error);
        }

        if (
            error.response.status === 401 &&
            originalRequest.url === baseURL + 'auth/jwt/refresh/'
        ) {
            window.location.href = '/account/Login/';
            return Promise.reject(error);
        }

        if (
            error.response.data.code === 'token_not_valid' &&
            error.response.status === 401 &&
            error.response.statusText === 'Unauthorized'
        ) {
            const refreshToken = localStorage.getItem('refresh_token');

            if (refreshToken) {
                const tokenParts = JSON.parse(atob(refreshToken.split('.')[1]));

                // exp date in token is expressed in seconds, while now() returns milliseconds:
                const now = Math.ceil(Date.now() / 1000);
                console.log(tokenParts.exp);

                if (tokenParts.exp > now) {
                    return axiosInstance
                        .post('/auth/jwt/refresh/', { refresh: refreshToken })
                        .then((response) => {
                            localStorage.setItem('access_token', response.data.access);
                            localStorage.setItem('refresh_token', response.data.refresh);

                            axiosInstance.defaults.headers['Authorization'] =
                                'Bearer ' + response.data.access;
                            originalRequest.headers['Authorization'] =
                                'Bearer ' + response.data.access;

                            return axiosInstance(originalRequest);
                        })
                        .catch((err) => {
                            console.log(err);
                        });
                } else {
                    console.log('Refresh token is expired', tokenParts.exp, now);
                    window.location.href = '/account/Login/';
                }
            } else {
                console.log('Refresh token not available.');
                window.location.href = '/account/Login/';
            }
        }

        // specific error handling done elsewhere
        return Promise.reject(error);
    }
);

export default axiosInstance;

请帮助我理解并将我指向相关资源以了解更多信息。

4

4 回答 4

1

我认为 react-query 的工作原理存在概念上的误解:从 query-function 返回的数据将在datareact-query 返回的属性中提供给您。不需要任何进一步的本地状态 - 特别是当您尝试在查询功能期间设置它时。如果您处于加载或错误状态,则该数据可能是undefined,因此您需要先检查它。还请查看文档中的所有示例

这是通常的样子,因为您的查询函数将返回一个数组:

const MyPlantMatrix=()=> {
  const {status, data, error, isFetching} = useQuery('myplantmatrix', async ()=>{
    const {data} = await axiosInstance.get("api_url/?format=json");
    console.log(data);
    return data;
  })

  // here, data will be potentially undefined
  
  if (status === 'loading') return <Spin/>
  if (status === 'error') return error.message

  // now, data should not be undefined

  const renderedPlantMatrix = data.map(...)

  return (
    <>
      {renderedPlantMatrix}
      <div>{isFetching ? 'Data is updating in background...' : ''}</div>
    </>
  )
}

或者,您可以if (data)在开始时进行检查,然后呈现您的数据。如果您在重新获取时遇到错误,这可能会更好,因为那样您将data 遇到错误,因此您必须根据具体情况决定是否更好地显示重新获取错误或缓存具有的(陈旧)数据,或两者兼而有之。

于 2021-01-17T11:22:38.080 回答
0

myPlantMatrix应该是一个map可以工作的数组,在您的数据获取之前和期间myPlantMatrix不会是数组类型。检查是否数组然后map

利用 Array.isArray(myPlantMatrix) && myPlantMatrix.map(...

于 2021-01-17T11:27:18.170 回答
0

我认为您不应该使用 useState 挂钩,因为反应查询提供默认数据并有效处理缓存,并且您在返回数据之前将数据设置为 setState 。不要使用 UseState 钩子,因为应该清楚 react 查询用于缓存、获取和更新数据,因此它会返回您更新的数据,并且在 react 中映射时始终使用

{plants?.assigned_plant_code.map(
                 plantcode => {
                     return <Tag>{plantcode}</Tag>
                 }
             ) }

“?” 是反应中的一个可选标记,它忽略了assigned_plant_code.map 它是未定义的,你也可以这样做

plants.length > 0  ? 
{plants?.assigned_plant_code.map(
                 plantcode => {
                     return <Tag>{plantcode}</Tag>
                 }
             ) }
    : <div>Error</div>
于 2021-11-27T14:19:29.087 回答
0

I think the problem is here. You need to first check that assigned_plant_code is an array and it has length > 0. The ? will make sure that assigned_plant_code exists before checking the length

{plants.assigned_plant_code?.length && plants.assigned_plant_code.map(
                     plantcode => {
                         return <Tag>{plantcode}</Tag>
                     }
                 ) }
于 2021-01-17T11:03:40.473 回答