J'essaye de montrer une liste de films utilisant redux et material ui.
FilmsService:
import React , { Component }from 'react'; import PropTypes from 'prop-types'; import {makeStyles, withStyles} from '@material-ui/core/styles'; import {getAllFilms} from "../store/actions/FilmActions"; import Button from '@material-ui/core/Button'; import Card from "@material-ui/core/Card/Card"; import CardActionArea from "@material-ui/core/CardActionArea/CardActionArea"; import CardMedia from "@material-ui/core/CardMedia/CardMedia"; import CardContent from "@material-ui/core/CardContent/CardContent"; import Typography from "@material-ui/core/Typography/Typography"; import CardActions from "@material-ui/core/CardActions/CardActions"; import connect from "react-redux/es/connect/connect"; import { withRouter } from 'react-router-dom'; const useStyles = makeStyles({ card: { maxWidth: 345, }, }); class FilmsCard extends Component { componentDidMount () { const {dispatch} = this.props; dispatch(getAllFilms()); } constructor(props) { super(props); this.state = { change: '' }; } render() { const films = this.props.films || []; return ( <Card> {films.map(film => { return( <CardActionArea> <CardMedia component="img" alt="Contemplative Reptile" height="140" image="/static/images/cards/contemplative-reptile.jpg" title="Contemplative Reptile" /> <CardContent> <Typography gutterBottom variant="h5" component="h2"> {film.show ? film.show.name : film.name} </Typography> <Typography variant="body2" color="textSecondary" component="p"> {film.show ? film.show.name : film.name} </Typography> </CardContent> </CardActionArea> )})} <CardActions> <Button size="small" color="primary"> Share </Button> <Button size="small" color="primary"> Learn More </Button> </CardActions> </Card> ); } } FilmsCard.propTypes = { classes: PropTypes.object.isRequired, }; const mapStateToProps = (state) => { return { films : state.filmreducer }; } const connectedVendorPage = withRouter(connect(mapStateToProps, null, null, { pure: false })(withStyles(useStyles)(FilmsCard))); export { connectedVendorPage as FilmsCard };
FilmAction:
const initialState = { films: [] } export function filmreducer(state = initialState, action) { switch (action.type) { case 'GET_FILMS': console.log(action); return{ ...state, films : action.payload.data }; case 'GET_FILMS_BY_NAME': return{ ...state, films : action.payload.data }; default: return state } }
FilmReducer:
export function getAllFilms() { return dispatch => { FilmServices.getAllFilms() .then((response) => { if (response) { dispatch(GET_FILMS(response)); } }) } }
3 Réponses :
Dans la méthode render (), supprimez cette ligne const {films} = this.props.films;
et essayez ceci:
const films = this.props.films || [];
et aussi, veuillez supprimer console.log (this.props.films)
dans le constructeur.
Mettez à jour FilmAction avec ceci:
export function getAllFilms() { return dispatch => { return FilmServices.getAllFilms() .then((response) => { if (response) { dispatch(GET_FILMS(response)); } }) } }
J'ai eu cette erreur maintenant: TypeError: Impossible de lire la propriété 'length' de undefined
pouvez-vous également indiquer le numéro de la ligne d'erreur? Vous n'obtenez de longueur dans aucun des codes ci-dessus.
J'ai eu l'erreur lorsque j'appelle
Tout d'abord, supprimez componentWillMount () car il est obsolète et vous ne devriez pas l'utiliser. Deuxièmement, obtenez-vous des journaux dans votre console après componentDidMount ()?
Non, je ne reçois aucun journal! seules erreurs: l'erreur ci-dessus s'est produite dans le composant
Je pense que le problème n'est pas dans le composant maintenant. La seule chose que vous devez changer dans le composant FilmsCard est const {films} = this.props.films;
ce que vous avez déjà fait. Mettez à jour votre question avec le dernier code de composant FilmsCard et fournissez également le code FilmReducer complet.
C'est bizarre maintenant car même si this.props.films est nul, les films const devraient être un tableau vide. Changez le code FilmAction comme je l'ai mentionné dans la réponse mise à jour et fournissez le code GET_FILMS () dans votre réponse.
@Muhammad Awais J'ai changé mon render () comme ceci et cela a fonctionné:
render() { const { classes } = this.props; const { films } = this.props.films; return ( <Card className={classes.card}> {films.map(film => { return( <CardActionArea> <CardMedia className={classes.media} component="img" alt="Contemplative Reptile" height="140" image="http://static.tvmaze.com/uploads/images/medium_portrait/168/421041.jpg" title="Contemplative Reptile" /> <CardContent> <Typography gutterBottom variant="h5" component="h2"> {film.show ? film.show.name : film.name} </Typography> <Typography variant="body2" color="textSecondary" component="p"> {film.show ? film.show.name : film.name} </Typography> </CardContent> </CardActionArea> )})} <CardActions> <Button size="small" color="primary"> Share </Button> <Button size="small" color="primary"> Learn More </Button> </CardActions> </Card> ); }
}
Aussi en changeant cette partie du code a fonctionné pour moi:
const styles = theme => ({ card: { maxWidth: 345, }, media: { height: 50, }, });
changé en ceci:
const useStyles = makeStyles({ card: { maxWidth: 345, }, });