未捕获的类型错误:无法读取 Reactjs 中未定义的属性"映射" - redux



我正在处理MongoDB、Express、React、Node(MERN(项目。我有一个问题;在更改redux文件以实现从Material UI/core<循环程序/>

我尝试过用不同的方式使用useSelector访问数据,甚至使用了shallowEqual方法。我还尝试调用DashBoardAdmin内部的getStudents((。同时还尝试使用useEffect来调度具有依赖项数组的(getStudents(((。到目前为止,一切都不起作用。然后尝试在chrome的inspect部分进行调试,在那里我发现,在第一次重新加载页面时,碰巧从action.paylod上的后端获取数据,但它无法填充到整个状态中。这可能是useSelector得到一个空数组&提供";无法读取未定义的属性"map">

我想,在reducers的students.js文件之后,在状态中引入了一个对象之后,出现了问题。我正在尽力调试。

我的index.js文件:

import React from "react";
import ReactDOM from "react-dom";
import "./Styles/index.css";
import App from "./App";
import { Provider } from "react-redux";
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import { reducers } from "./redux/reducers/index";
const composeEnhancers =
typeof window === "object" && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
: compose;
const enhancer = composeEnhancers(compose(applyMiddleware(thunk)));
const store = createStore(reducers, enhancer);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);

我的app.js文件:

import React, { useEffect, useState } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import "./Styles/App.css";
import AdminSignIn from "./Pages/AdminSignIn";
import DashBoardAdmin from "./Pages/Admin";
import NavbarAdmin from "./Navbars/NavbarAdmin";
import BottomNavbar from "./Navbars/bottomNavbar";
import { useDispatch } from "react-redux";
import { Typography } from "@material-ui/core";
import { NotFound } from "./Not_Found/NotFound";
import { getStudents } from "./redux/actions/studentAction";
function App() {
const user = JSON.parse(localStorage.getItem("account"));
const dispatch = useDispatch();
useEffect(() => {
dispatch(getStudents());
}, [dispatch]);
return (
<>
<Router>
{user?.result?._id ? (
<NavbarAdmin />
) : (
<Typography variant="h2">{"Fetch"} Organization Name</Typography>)}
<Switch>
<Route path="/" exact>
<AdminSignIn />
</Route>
<Route path="/dashboard" exact>
<DashBoardAdmin />
</Route>

<Route >
<NotFound />
</Route>
</Switch>
<BottomNavbar />
</Router>
</>
);
}
export default App;

我的DashBoardAdmin.js文件:

import { Box, Button, Card, CardHeader, Chip, CircularProgress, Divider, Table, TableBody, TableCell, TableHead, TableRow, TableSortLabel, Tooltip} from "@material-ui/core";
import { Link } from 'react-router-dom'
import ArrowRightIcon from "@material-ui/icons/ArrowRight";
import moment from "moment";
import PerfectScrollbar from "react-perfect-scrollbar";
import { useSelector } from "react-redux";
const DashBoardAdmin = () => {
const { students, isLoading } = useSelector((state) => state.students);
return (
<div className="padding-grid">
<Card>
<CardHeader title="Latest updates on students" />
<Divider />
<PerfectScrollbar>
<Box sx={{ minWidth: 800 }}>
<Table>
<TableHead>
<TableRow>
<TableCell>Roll Number</TableCell>
<TableCell>Name of student</TableCell>
<TableCell sortDirection="desc">
<Tooltip enterDelay={300} title="Sort">
<TableSortLabel active direction="desc">
Date of Admission
</TableSortLabel>
</Tooltip>
</TableCell>
<TableCell>Status</TableCell>
</TableRow>
</TableHead>
{isLoading ? (
<CircularProgress />
) : (
<TableBody>
{students.map((stu) => (
<TableRow hover key={stu.id}>
<TableCell>{stu.rollNumber}</TableCell>
<TableCell>{stu.firstName}  {" "} {stu.lastName} + {" "} {stu.surname}</TableCell>
<TableCell>
{moment(stu.createdAt).format("DD/MM/YYYY")}
</TableCell>
<TableCell>
<Chip color="primary" label={stu.status} size="small" />
</TableCell>
</TableRow>
))}
</TableBody>
)}
</Table>
</Box>
</PerfectScrollbar>
<Box
sx={{
display: "flex",
justifyContent: "flex-end",
p: 2,
}}>
<Link to="/students-info">
<Button
color="primary"
endIcon={<ArrowRightIcon />}
size="small"
variant="text">
View all
</Button>
</Link>
</Box>
</Card>
</div>
);
};
export default DashBoardAdmin;

我的redux studentAction.js文件:

import { FETCH_STUDENTS, START_LOADING, END_LOADING } from "../constants/actionTypes";
import * as api from "../api/index.js";
export const getStudents = () => async (dispatch) => {
try {
dispatch({ type: START_LOADING })
const { data } = await api.fetchStudents();
dispatch({ type: FETCH_STUDENTS, payload: data });
dispatch({ type: END_LOADING})
} catch (error) {
console.log(error);
}
};

我的API index.js文件:

import axios from "axios";
const API = axios.create({ baseURL: "http://localhost:5000" });
API.interceptors.request.use((req) => {
if (localStorage.getItem("account")) {
req.headers.Authorization = `Bearer ${
JSON.parse(localStorage.getItem("account")).token
}`;
}
return req;
});
export const fetchStudents = () => API.get("/students-info");

students.js的reducers和最好的猜测是这里出了问题,或者是在我包含isLoading:之后开始的

import { FETCH_STUDENTS, START_LOADING, END_LOADING } from "../constants/actionTypes";
function students(state = { isLoading: true, students: [] }, action) {
switch (action.type) {
case START_LOADING:
return { ...state, isLoading: true };
case END_LOADING:
return { ...state, isLoading: false };

case FETCH_STUDENTS:
return { ...state, students: action.payload.data };

default:
return state;
}
}
export default students;

index.js联合收割机减速器文件:

import { combineReducers } from "redux";
import students from "./students";
import auth from "./auth";
export const reducers = combineReducers({ students, auth });

我得到的错误是:

Uncaught TypeError: Cannot read property 'map' of undefined
at DashBoardAdmin (DashBoardAdmin.js:51)
at renderWithHooks (react-dom.development.js:14985)
at updateFunctionComponent (react-dom.development.js:17356)
at beginWork (react-dom.development.js:19063)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
at invokeGuardedCallback (react-dom.development.js:4056)
at beginWork$1 (react-dom.development.js:23964)
at performUnitOfWork (react-dom.development.js:22776)
at workLoopSync (react-dom.development.js:22707)
at renderRootSync (react-dom.development.js:22670)
at performSyncWorkOnRoot (react-dom.development.js:22293)
at react-dom.development.js:11327
at unstable_runWithPriority (scheduler.development.js:468)
at runWithPriority$1 (react-dom.development.js:11276)
at flushSyncCallbackQueueImpl (react-dom.development.js:11322)
at flushSyncCallbackQueue (react-dom.development.js:11309)
at batchedUpdates$1 (react-dom.development.js:22387)
at Object.notify (Subscription.js:19)
at Subscription.notifyNestedSubs (Subscription.js:90)
at Subscription.handleChangeWrapper (Subscription.js:95)
at Object.dispatch (redux.js:297)
at dispatch (<anonymous>:3856:17)
at index.js:11
at dispatch (redux.js:659)
at studentAction.js:35

和另一个错误:

Warning: validateDOMNesting(...): <div> cannot appear as a child of <table>.
at div
at CircularProgress (http://localhost:4000/static/js/vendors~main.chunk.js:80761:23)
at WithStyles (http://localhost:4000/static/js/vendors~main.chunk.js:119309:31)
at table
at Table (http://localhost:4000/static/js/vendors~main.chunk.js:102171:23)
at WithStyles (http://localhost:4000/static/js/vendors~main.chunk.js:119309:31)
at div
at StyledComponent (http://localhost:4000/static/js/vendors~main.chunk.js:119080:28)
at div
at ScrollBar (http://localhost:4000/static/js/vendors~main.chunk.js:231982:5)
at div
at Paper (http://localhost:4000/static/js/vendors~main.chunk.js:94231:23)

我使用students.js文件中redux的简单语法从后端获取数据:

import { FETCH_STUDENTS } from "../constants/actionTypes";
export default (students = [], action) => {
switch (action.type) {
case FETCH_STUDENTS:
return action.payload;
default:
return students;
}
};

需要获得一种替代方法来实现对UI 的isLoading或START_LOADING/END_LOADING调度

看了你的app.js之后,我发现你在使用thunk,我认为你必须使用函数,而不是直接传递对象。

此外,我添加了一个操作来获取错误,以防

studentAction.js

import {
FETCH_STUDENTS,
START_LOADING,
END_LOADING,
} from "../constants/actionTypes";
import * as api from "../api";
const startLoading = () => {
return {
type: START_LOADING,
};
};
const fetchStudents = (data) => {
return {
type: FETCH_STUDENTS,
data,
};
};
const endLoading = (error) => {
return {
type: END_LOADING,
error,
};
};
export const getStudents = () => {
return async (dispatch) => {
dispatch(startLoading());
try {
const { data } = await api.fetchStudents()

dispatch(fetchStudents(data))
} catch (error) {
dispatch(endLoading(error.message));
}
};
};

students.js

import {
FETCH_STUDENTS,
START_LOADING,
END_LOADING,
} from "../../constants/actionTypes";
const initialState = {
isLoading: false,
error: "",
students: [],
};
function students(state = initialState, action) {
switch (action.type) {
case START_LOADING:
return { ...state, isLoading: true };
case END_LOADING:
return { ...state, isLoading: false, students: [], error: action.error };
case FETCH_STUDENTS:
return {
...state,
isLoading: false,
students: action.data,
};
default:
return state;
}
}
export default students;

你的app.js和index.js对我来说是正确的

在Admin.js中,您可以使用这种条件

import { useSelector } from "react-redux";
const DashBoardAdmin = () => {
const { students, isLoading, error } = useSelector((state) => state.students);
return (
<>
{error === "" && (
<div className="padding-grid">
...
{isLoading || !students.length > 0 ? (
<h1>loading...</h1>
) : (
<div>
{students.map((stu) => (
<p key={stu.id}>{JSON.stringify(stu)}</p>
))}
</div>
)}
...
</div>
)}
</>
);
};
export default DashBoardAdmin;

相关内容

  • 没有找到相关文章