错误:无效的挂钩调用。使用钩子的函数在类的列表内被调用

时间:2019-11-17 11:17:49

标签: reactjs material-ui

我正在使用MaterialUI。我的仪表板上有一张卡片列表。 My Dash是扩展React.Component的类。我的卡是使用挂钩useState的功能。我的破折号正在使用.map()来建立牌列表。我的卡具有“显示数据”的功能。

Dashboard.js

import React from 'react';
import { withStyles } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
import Grid from '@material-ui/core/Grid';
import Service from '../app/Service';
import Copyright from '../components/Copyright'
import CardContact from '../components/CardContact'



const styles = theme => ({
  root: {
    display: 'flex',
    paddingTop: '80px'
  },
  appBarSpacer: theme.mixins.toolbar,
  content: {
    flexGrow: 1,
    height: '100vh',
    overflow: 'auto',
  },
  container: {
    paddingTop: theme.spacing(4),
    paddingBottom: theme.spacing(4),
  },

});




class Dashboard extends React.Component {
 state ={

 }
  componentDidMount() {
    this.contactsFormatted();
  }



  contactsFormatted = async () => {
    try {
     const res = await Service.get('/all-contacts');
     const contacts = res.data;

     this.setState({
       Contacts: contacts.map((contact, i) => (
         CardContact(contact, i)
       ))
     })
    } catch(err){
      console.log(err)
    }
  }


  render(){
  const { classes } = this.props;

  return (
    <div className={classes.root}>
        <Container maxWidth="lg" className={classes.container}>
          <Grid container spacing={3}>
            {this.state.Contacts}
          </Grid>

          <Copyright />
        </Container>
    </div>
  );
}
}



export default withStyles(styles)(Dashboard);

我的CardContact.js

import React from 'react'
import Card from '@material-ui/core/Card';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import Grid from '@material-ui/core/Grid';
import Collapse from '@material-ui/core/Collapse';

const CardContact = ({name, office, occupation_area, tel, email}, i) => {

    const [expanded, setExpanded] = React.useState(false);
    const handleExpandClick = () => {
      setExpanded(!expanded);
    }

    return (
      <Grid xs={12} style={{ paddingBottom: 32 }} key={i} item={true}>
      <Card >
        <CardContent>
          <Typography variant="h5" component="h2">  
            Nome: {name}
          </Typography>
          <Typography  color="textSecondary" gutterBottom>
            Cargo: {office}
          </Typography>
          <Typography  color="textSecondary" gutterBottom>
            Área de atuação: {occupation_area}
          </Typography>
        </CardContent>



        <CardActions style={{justifyContent: 'flex-end'}} >
          <Button  size="small" 
          onClick={handleExpandClick}
          aria-expanded={expanded}>Revelar</Button>
        </CardActions>

        <Collapse in={expanded} timeout="auto" unmountOnExit>
        <CardContent>
          <Typography  color="textSecondary" gutterBottom>
            Telefone: {tel}
          </Typography>
          <Typography  color="textSecondary" gutterBottom>
            E-mail: {email}
          </Typography>
        </CardContent>
      </Collapse>
      </Card>
      </Grid>
    )
  }

  export default CardContact;

Hooks用法有什么问题?

2 个答案:

答案 0 :(得分:0)

您正在CardContact方法内调用contactsFormatted。由于contactsFormatted不是有效的React组件,因此React引发错误。带挂钩的React组件只能从React组件的有效渲染函数(类或函数)中调用/渲染。

尝试一下:

contactsFormatted = async () => {
    try {
     const res = await Service.get('/all-contacts');
     const contacts = res.data;

     this.setState({contacts})
    } catch(err){
      console.log(err)
    }
  }

在渲染中:

render(){
  const { classes } = this.props;

  return (
    <div className={classes.root}>
        <Container maxWidth="lg" className={classes.container}>
          <Grid container spacing={3}>
            {this.state.contacts.map((contact, i) => (
              <CardContact contact={contact} index={i} />
            )}
          </Grid>

          <Copyright />
        </Container>
    </div>
  );
}

现在,完整数据将以CardContact属性的形式在contact组件中可用

答案 1 :(得分:0)

如先前的回答所述,这不是渲染卡片的正确方法。与其将组件存储为“联系人”状态,不如将存储卡对应的对象存储为“联系人”状态,如下所示:

    contactsFormatted = async () => {
    try {
     const res = await Service.get('/all-contacts');
     const contacts = res.data;

     this.setState({
       Contacts: [...Contacts].concat(contacts),
     })
    } catch(err){
      console.log(err)
    }
  }

此外,您应该按如下方式绘制卡片:

return (
    <div className={classes.root}>
        <Container maxWidth="lg" className={classes.container}>
          <Grid container spacing={3}>
            {(this.state.Contacts || []).map((contact, i) => <CardContact contact={contact} i={i} />)}
          </Grid>

          <Copyright />
        </Container>
    </div>
  );