繁体   English   中英

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

[英]when I use "useCallback " I get a TypeError error

我有 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>
    );
  },
);

错误是:

类型错误:无法读取未定义的属性“纸”

参考这一行

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

我将这些类添加到 popover 的纸类中。

我不习惯 useCallback 和 new 来反应所以我迷路了。

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

您创建的函数需要传递 7 项内容。 但是当你使用它时,你只传入4个:

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

所以剩下的3个在函数内都是未定义的。 在组件顶部定义的 anchorEl、classes 和 handleClick 变量在体验中不可见,因为这些变量被“遮蔽”了。

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

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

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

所以我建议完全删除 useCallback :

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM