无法读取数据 null 反应的属性
2021-03-04
282
我的 api 出了点问题,每次我登录并进入
Dashboard 页面
时,它都会返回
TypeError: Cannot read property 'data' of null
。
这是一个使用 JWT 身份验证登录的简单应用程序,这意味着我需要在登录时将令牌设置在语言环境存储中,我已经这样做了。但是令牌会在 15 分钟后过期,需要刷新令牌。以下是 api 的详细信息:
Retrieve the necessary data for the dashboard at 'https://freddy.codesubmit.io/dashboard'.
This endpoint requires a 'Authorization: Bearer access_token' header.
Use the access token that you retrieved from Login.
Keep in mind that access tokens expire after 15 minutes.
You may request a fresh access token by sending a POST request to https://freddy.codesubmit.io/refresh' with the 'Authorization: Bearer refresh_token' header.
我还没有完成刷新令牌部分,因为我不确定怎么做,我想这可能是问题所在?由于令牌过期而超时?
这是我的登录信息:
import React, {useContext, useState} from 'react';
import { useHistory } from 'react-router-dom'
import axios from 'axios';
import { AuthContext } from '../hooks/UserContext';
import Logo from '../images/Freddys_Logo.svg';
import '../css/Login.css';
const Login = () => {
const [userError, setUserError] = useState("");
const [passError, setPassError] = useState("");
const {setLoggedIn} = useContext(AuthContext);
let history = useHistory();
const [authInfo, setAuthInfo] = useState({
username: "",
password: ""
})
const handleChange = e => {
setAuthInfo({
...authInfo,
[e.target.name]: e.target.value
})
}
const handleSubmit = e => {
e.preventDefault();
axios.post('https://freddy.codesubmit.io/login', authInfo)
.then(res => {
setLoggedIn(true);
localStorage.setItem("token", res.data.access_token);
localStorage.setItem("refresh_token", res.data.refresh_token);
history.push('/dashboard')
})
.catch(err => console.log(err))
}
return (
<div className="wrapper">
<div className="logoContainer">
<div className="heading">
<p>
Freddy's
<br/>
Artisanal
<br/>
Halloween
<br/>
Candy Shop
</p>
</div>
<div className="svgLogo">
<img src={Logo} className="svgLogo" alt="image" />
</div>
</div>
<div className="inputContainer">
<form method="POST" onSubmit={handleSubmit}>
<input
name="username"
type="text"
value={authInfo.username}
placeholder="username"
onChange={handleChange}
className="input"
/>
<input
name="password"
type="password"
value={authInfo.password}
placeholder="************"
onChange={handleChange}
className="input"
/>
<input
type="submit"
value="Login"
className="submitButton"
/>
</form>
</div>
ElmStreet2019
</div>
)
}
export default Login;
这是我用来获取数据的 api:useFetch.js
import { useEffect, useState } from "react";
import axios from "axios";
const useFetch = async => {
const [response, setResponse] = useState(null);
const [error, setError] = useState(null);
const token = localStorage.getItem("token");
useEffect(() => {
async function fetchData() {
try {
const res = await axios.get(
"https://freddy.codesubmit.io/dashboard"
, {headers: {Authorization: `Bearer ${token}`}});
setResponse(res);
} catch (error) {
setError(error, "err");
}
}
fetchData();
}, [token]);
return { response, error };
};
export default useFetch;
这是我尝试显示数据的页面:Dashboard.jsx
import React, {useState, useContext, useEffect} from 'react';
import Layout from './Layout';
import Table from './Table';
import axios from 'axios';
import { useHistory } from 'react-router-dom'
import { AuthContext } from '../hooks/UserContext'
import useFetch from "../hooks/useFetch";
import Switch from "react-switch";
import BarChart from 'react-bar-chart';
import '../css/Dashboard.css'
const Dashboard = () => {
const {} = useContext(AuthContext);
const { response, error } = useFetch();
const [checked, setChecked] = useState(false);
const refreshToken = localStorage.getItem("refresh_token")
const handleCheckedChange = () => {
setChecked(!checked)
}
const lastSevenDays = [
{text: 'yesterday', value: 500},
{text: 'today', value: 1300},
{text: 'day 3', value: 300},
{text: 'day 4', value: 300},
{text: 'day 5', value: 300},
{text: 'day 6', value: 300},
{text: 'day 7', value: 300},
];
const lastTwelveMonths = [
{text: 'this month', value: 500},
{text: 'today', value: 1300},
{text: 'day 3', value: 300},
{text: 'day 4', value: 300},
{text: 'day 5', value: 300},
{text: 'day 6', value: 300},
{text: 'day 7', value: 300},
];
const margin = {top: 10, right: 20, bottom: 30, left: 40};
console.log(error)
return (
<Layout>
<h1>Dashboard</h1>
<div className="container">
<div className="item">
<span className="textStyle">Today</span>
<p>$1456 / 9 orders</p>
</div>
<div className="item">
<span className="textStyle">Today</span>
<p>$1456 / 9 orders</p>
</div>
<div className="item">
<span className="textStyle">Today</span>
<p>$1456 / 9 orders</p>
</div>
</div>
<div className="revenueContainer">
<div className="title">
{!checked ? <h2>Revenue (last 7 days)</h2> : <h2>Revenue (last 12 months)</h2>}
</div>
<div className="toggle">
<Switch
onChange={handleCheckedChange}
checked={checked}
onColor="#86d3ff"
onHandleColor="#2693e6"
uncheckedIcon={false}
checkedIcon={true}
boxShadow="0px 1px 5px rgba(0, 0, 0, 0.6)"
activeBoxShadow="0px 0px 1px 10px rgba(0, 0, 0, 0.2)"
/>
</div>
</div>
<div>
<div style={{width: '100%'}}>
{!checked ? (
<BarChart
ylabel=''
width={600}
height={300}
margin={margin}
data={lastSevenDays}
/>
) : !!checked ? (
<BarChart
ylabel=''
width={600}
height={300}
margin={margin}
data={lastTwelveMonths}
/>
) : null}
</div>
</div>
<h2>Bestsellers</h2>
<Table bestsellers={response.data.dashboard.bestsellers} />
</Layout>
)
}
export default Dashboard;
Dashboard.js 中的表格组件
import React from 'react';
import '../css/Table.css';
const Table = ({bestsellers}) => {
if(bestsellers === undefined || null) {
return <div> loading...</div>
}
return (
<div className="tableContainer">
<div className="headingContainer">
<div className="tableHeader"><span className="tableHeading">Product Name</span></div>
<div className="tableHeader"><span className="tableHeading">Price</span></div>
<div className="tableHeader"><span className="tableHeading"># Units Sold</span></div>
<div className="tableHeader"><span className="tableHeading">Revenue</span></div>
</div>
{bestsellers
.slice(0, 3)
.map(row => (
<div className="rowContainer" key={row.product.id}>
<div className="tableItem">
<span className="tableItemText">{row.product.name}</span>
</div>
<div className="tableItem">
<span className="tableItemText">N/A</span>
</div>
<div className="tableItem">
<span className="tableItemText">{row.units}</span>
</div>
<div className="tableItem">
<span className="tableItemText">{row.revenue}</span>
</div>
</div>
))}
</div>
)
}
export default Table;
1个回答
您的
useFetch
钩子最初返回
null
作为
response
。在
Dashboard
组件中,您尝试将
response.data.dashboard.bestsellers
传递给
Table
组件,而不检查
response
是否不为
null
/
undefined
。
根据您的开发环境的现代程度,您可以编写:
<Table bestsellers={response && response.data.dashboard.bestsellers} />
或:
<Table bestsellers={response?.data.dashboard.bestsellers} />
Wojciech Maj
2021-03-04