После развертывания моего приложения на Heroku оно вылетает с сообщением InternalError: "too much recursion"
затем Invariant Violation: "Minified React error #31; visit https://reactjs.org/docs/error-decoder.html?invariant=31&args[]=InternalError%3A%20too%20much%20recursion&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings....
, когда я пытаюсь получить доступ к домашней странице. Страница также ничего не отображает. Другие страницы работают нормально, но мне нужно отредактировать URL в браузере, чтобы получить к ним доступ. Я не вижу, что я делаю неправильно.
Если я попытаюсь отследить, сколько раз была выполнена выборка в componentDidMount, ошибка исчезнет. Я не вижу проблемы с вызванным также фумингом. Я проверил конечные полуколонны JS после тегов и убедился, что все компоненты возвращают действительный jsx.
Главная / index.js
import React, { Component } from "react";
import PageWrapper from "../PageWrapper";
import { connect } from "react-redux";
import { fetchHighlightedCourses } from "../../store/actions";
import AsyncWrapper from "../AsyncWrapper";
const AsyncCourseList = AsyncWrapper(() => import("./CourseList"));
class Home extends Component {
componentDidMount() {
const { highlightedCourses } = this.props;
if (!Array.isArray(highlightedCourses) || highlightedCourses.length === 0)
this.props.fetchHighlightedCourses();
}
_renderCourseList = () => {
const { highlightedCourses } = this.props;
console.log(highlightedCourses);
if (Array.isArray(highlightedCourses) && highlightedCourses.length > 0)
return <AsyncCourseList courses={highlightedCourses} />;
return <div> </div>
};
render() {
return (
<PageWrapper title="Acceuil">
{this._renderCourseList()}
</PageWrapper>
);
}
}
const mapStateToProps = state => {
return {
highlightedCourses: state.explore.highlightedCourses
};
};
export default connect(
mapStateToProps,
{ fetchHighlightedCourses }
)(Home);
Главная / CourseList.js
import React from "react";
import classNames from "classnames";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import { withStyles } from "@material-ui/core/styles";
import { Link as RouterLink } from "react-router-dom";
import Link from "@material-ui/core/Link";
import CourseCard from "./CourseCard";
const styles = theme => ({
layout: {
width: "auto",
marginLeft: theme.spacing.unit * 3,
marginRight: theme.spacing.unit * 3
},
cardGrid: {
padding: `${theme.spacing.unit * 4}px 0`
},
catalogTitle: {
color: theme.palette.text.secondary,
marginBottom: theme.spacing.unit * 3
},
catalogLink: {
marginTop: theme.spacing.unit * 3
}
});
const CourseList = ({ classes, courses }) => {
if (Array.isArray(courses))
return (
<div className={classNames(classes.layout, classes.cardGrid)}>
<Typography variant="h6" className={classes.catalogTitle}>
{"Que voulez-vous apprendre aujourd'hui?"}
</Typography>
<Grid container spacing={24}>
{courses.map((course, index) => (
<Grid item key={index}>
<CourseCard course={course} />
</Grid>
))}
</Grid>
<Typography variant="h6" className={classes.catalogLink}>
<Link component={RouterLink} to={`/explore/classes`} underline="none">
{"Voir plus des Cours >"}
</Link>
</Typography>
</div>
);
return <div> </div>
};
export default withStyles(styles)(CourseList);
Главная / CourseCard.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
import Card from "@material-ui/core/Card";
import CardActionArea from "@material-ui/core/CardActionArea";
import CardActions from "@material-ui/core/CardActions";
import MoreHoriz from "@material-ui/icons/MoreHoriz";
import CardContent from "@material-ui/core/CardContent";
import Grow from "@material-ui/core/Grow";
import CardMedia from "@material-ui/core/CardMedia";
import Typography from "@material-ui/core/Typography";
import IconButton from "@material-ui/core/IconButton";
import DefaultImage from "./default.jpg";
import Menu from "@material-ui/core/Menu";
import MenuItem from "@material-ui/core/MenuItem";
import { Link as RouterLink } from "react-router-dom";
import Link from "@material-ui/core/Link";
const styles = {
card: {
width: 190,
height: "100%",
display: "flex",
flexDirection: "column"
},
media: {
height: 90
},
courseTitle: {
height: 65
//overflowX: 'auto'
},
cardContent: {
flexGrow: 1
}
};
class CourseCard extends Component {
constructor(props) {
super(props);
this.state = {
anchorEl: null
};
}
handleMoreClick = event => {
this.setState({ anchorEl: event.currentTarget });
};
handleMoreClose = () => {
this.setState({ anchorEl: null });
};
render() {
const { classes, course } = this.props;
const { anchorEl } = this.state;
return (
<Grow in timeout={300}>
<Card className={classes.card}>
<CardActionArea>
<Link
component={RouterLink}
to={`/explore/classe/${course._id}`}
underline="none"
>
<CardMedia
className={classes.media}
image={course.img || DefaultImage}
title="Default image"
/>
<CardContent className={classes.cardContent}>
<Typography
gutterBottom
variant="h6"
component="h6"
className={classes.courseTitle}
>
{course.title}
</Typography>
</CardContent>
</Link>
</CardActionArea>
<CardActions>
<IconButton
color="primary"
aria-label="more_options"
onClick={this.handleMoreClick}
>
<MoreHoriz />
</IconButton>
<Menu
id="more_options"
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={this.handleMoreClose}
>
<MenuItem onClick={this.handleMoreClose}>S'inscrire</MenuItem>
<MenuItem onClick={this.handleMoreClose}>Détails</MenuItem>
</Menu>
</CardActions>
</Card>
</Grow>
);
}
}
CourseCard.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(CourseCard);
Следующее исправляет проблему, но я хотел бы знать, почему.
class Home extends Component {
state = { fetched: 0 };
componentDidMount() {
const { highlightedCourses } = this.props;
if (
(!Array.isArray(highlightedCourses) || highlightedCourses.length === 0) &&
this.state.fetched < 3
) {
this.setState(prev => ({ fetched: prev.fetched + 1 }));
this.props.fetchHighlightedCourses();
}
}
...//the rest is the same
}
Вот действие
export const fetchHighlightedCourses = () => async dispatch => {
try {
dispatch({
type: HIGHLIGHTED_COURSE_LOADING
});
const res = await axios.get(highlightedCourseURL);
if (res.status === 200 && res.data.success) {
return await dispatch({
type: HIGHLIGHTED_COURSE_SUCCESS,
payload: res.data.content
});
}
return await dispatch({
type: HIGHLIGHTED_COURSE_FAILLURE,
payload: res.data.message
});
} catch (error) {
let message;
if (error.response && error.response.data && error.response.data.message)
message = error.response.data.message;
else message = "Erreur survenue lors du chargement de vos contacts";
return await dispatch({
type: HIGHLIGHTED_COURSE_FAILLURE,
payload: message
});
} finally {
return await dispatch({
type: HIGHLIGHTED_COURSE_DONE
});
}
};
Спасибо