当我使用“ useCallback”时,出现TypeError错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当我使用“ useCallback”时,出现TypeError错误相关的知识,希望对你有一定的参考价值。

我有const经验,可以在弹出窗口中创建6种经验。我应该向其中添加useCallback,但是当我走时我得到了错误。

这是我的组件经验

import React,  memo, useCallback, useState  from 'react';
import PropTypes from 'prop-types';
import  makeStyles  from '@material-ui/styles';
import Typography from '@material-ui/core/Typography';
import clsx from 'clsx';
import Button from '@material-ui/core/Button';
import Popover from '@material-ui/core/Popover';
import gastronomia from 'assets/experiences/gastronomia.jpg';
import productos from 'assets/experiences/productos.jpg';
import giftcard from 'assets/experiences/giftcard.jpg';
import diversion from 'assets/experiences/diversion.jpg';
import deporte from 'assets/experiences/deporte.jpg';
import belleza from 'assets/experiences/belleza.jpg';
import gastronomiaExperiences from 'data/gastronomia';
import productosExperiences from 'data/productos';
import giftcardExperiences from 'data/giftcard';
import diversionExperiences from 'data/diversion';
import deporteExperiences from 'data/deporte';
import bellezaExperiences from 'data/belleza';

// Proptypes definitions to the component.
const propTypes = 
  /** Custom root className. */
  className: PropTypes.string,
;

// Default props definitions.
const defaultProps = 
  className: null,
;

// Component's styles
const useStyles = makeStyles(theme => (
  root: 
    display: 'block',
    margin: '0 auto',
    maxWidth: '50%',
    [theme.breakpoints.down('md')]: 
      maxWidth: '70%',
    ,
    [theme.breakpoints.down('sm')]: 
      maxWidth: '100%',
    ,
    '& .experiences-column': 
      display: 'inline-block',
      verticalAlign: 'top',
      textAlign: 'center',
      '&.col1': 
        width: '36.31%',
        [theme.breakpoints.down('sm')]: 
          width: 'initial',
        ,
      ,
      '&.col2': 
        width: '63.69%',
        [theme.breakpoints.down('sm')]: 
          width: 'initial',
        ,
      ,
      '& .experience': 
        padding: 2,
        position: 'relative',
        '& img': 
          width: '100%',
          display: 'block',
        ,
        '& .experience-title': 
          position: 'absolute',
          bottom: 30,
          left: 0,
          right: 0,
          textAlign: 'center',
        ,
      ,
    ,
  ,
  paper: 
    width: '50%',
    left: '25% !important',
    height: '280px',
    '& img': 
      width: '100px',
      padding: '0 10px 0 10px',
    ,
  ,
  gastronomia: 
    backgroundColor: 'rgba(0,185,208,0.9)',
  ,
  giftcard: 
    backgroundColor: 'rgba(221,165,174,0.9)',
  ,
  deporte: 
    backgroundColor: 'rgba(189,143,205,0.9)',
  ,
  productos: 
    backgroundColor: 'rgba(221,165,174,0.9)',
  ,
  diversion: 
    backgroundColor: 'rgba(255,176,10,0.9)',
  ,
  belleza: 
    backgroundColor: 'rgba(229,166,187,0.9)',
  ,
  '@media screen and (max-width: 1024px)': 
    paper: 
      width: '70%', 
      left: '15% !important',
    ,
  ,
  '@media screen and (max-width: 480px)': 
   paper: 
    width: '100%',  
    left: '0% !important',  
    height: '350px',
  ,
,
),  name: 'ExperiencesStyle' );

     */const Experiences = memo(
  (props) => 
    const  className  = props;
    const classes = useStyles(props);

    const [anchorEl, setAnchorEl] = useState(null);

    const handleClick = (event) => 
      setAnchorEl(anchorEl ? null : event.currentTarget);
    ;

    const handleClose = () => 
      setAnchorEl(null);
    ;

    // const open = Boolean(anchorEl);

    const experience = useCallback((img, title, id, popoverCategory, anchorEl, classes, handleClick) => (
      <div
        className="experience"
        aria-describedby=id
        id=id
        onClick=handleClick
        onKeyDown=handleClick
        role="button"
        tabIndex="0"
      >
        <img
          data-sizes="auto"
          className="lazyload"
          data-src=img
          alt=title
        />
        <div className="experience-title">
          <Typography
            color="textSecondary"
            variant="subtitle2"
            className="highlight highlight1"
            display="inline"
          >
             title 
          </Typography>
        </div>

        <Popover
          id=id
          open=anchorEl && anchorEl.id === id
          anchorEl=anchorEl
          onClose=handleClose
          classes=paper: clsx(classes.paper, classes[id])
        >
          <div>
            <Button onClickAway=handleClose>x</Button>
            <div>
              
              popoverCategory.map(url => (

                <img
                  key=url
                  data-sizes="auto"
                  className="lazyload"
                  src=url
                  alt=title
                />
              ))
            
            </div>
          </div>
        </Popover>
      </div>
    ), []);

    return (
      <div className=clsx(classes.root, className)>
        <div className="experiences-column col1">
          experience(gastronomia, 'GASTRONOMÍA', 'gastronomia', gastronomiaExperiences)
          experience(giftcard, 'GIFT CARD', 'giftcard', giftcardExperiences)
          experience(deporte, 'DEPORTE', 'deporte', deporteExperiences)
        </div>
        <div className="experiences-column col2">
          experience(productos, 'PRODUCTOS', 'productos', productosExperiences)
          experience(diversion, 'DIVERSIÓN', 'diversion', diversionExperiences)
          experience(belleza, 'BELLEZA', 'belleza', bellezaExperiences)
        </div>
      </div>
    );
  ,
);

错误是:

TypeError:无法读取未定义的属性'paper'

引用此行

classes=paper: clsx(classes.paper, classes[id])

将类添加到弹出框的纸类中的位置。

我不习惯使用Callback和new进行响应,所以我迷路了。

答案

const experience = useCallback((img,title,id,popoverCategory,anchorEl,classes,handleClick)=>(

您创建的函数希望将7项内容传入其中。但是,当您使用它时,您只需传递4:

经验(美食家,'GASTRONOMÍA','美食家',美食家经验)

因此其余3个在函数内都未定义。在组件内部定义的anchorEl,class和handleClick变量在内部体验中不可见,因为这些变量已被“阴影化”。

因此,您可以通过简单地从函数定义中删除最后3个参数来停止隐藏变量:

const experience = useCallback((img, title, id, popoverCategory) => (

但是,我必须表示useCallback似乎并没有为您做任何事情。 useCallback的好处是,您可以让experience变量从一个渲染到下一个成为相同的引用,但这似乎并不是您需要的功能。您的组件永远不会尝试比较experience的引用,也不会将experience传递到可能在shouldComponentUpdate或React.memo中进行检查的任何其他组件。

所以我建议您完全删除useCallback:

const experience = (image, title, id, popoverCategory) => (

以上是关于当我使用“ useCallback”时,出现TypeError错误的主要内容,如果未能解决你的问题,请参考以下文章

将数组值放在`usecallback deps`中

如何在 useCallback 中使用 ESlint 允许 IIFE 语法?

react useCallback notice

为啥回调中的 React useState 依赖项为空?

useMemo和useCallback的区别和使用

如何在自定义挂钩上使用 useCallback?