繁体   English   中英

反应 function 不会从功能组件传递到功能组件

[英]React function not passing down from functional to functional component

我已经习惯了 class 组件,现在正试图更习惯于钩子,所以我正在深入研究功能组件。

遇到一个棘手的问题,因为我无法将 function 从一个功能组件传递到其功能组件子组件。

在父组件中:

import React, { useState, useEffect } from 'react';
import { Link } from 'gatsby';
import { MenuList, MenuItem } from '@material-ui/core';
import { withCookies, Cookies } from 'react-cookie';
import { ExpandMore } from '@material-ui/icons';
import PropTypes from 'prop-types';
import styles from '../styles/nav.module.scss';
import NavDrawer from './navDrawer';

const activeStyle = {
   color: '#445565',
   backgroundColor: '#de1b',
   borderColor: '#ced4da',
};

const NavMobile = (props) => {
const [isOpenProductsMenu, setIsOpenProductsMenu] = useState(false);
const [isOpenServicesMenu, setIsOpenServicesMenu] = useState(false);
const [isAdmin, setIsAdmin] = useState(false);

const { cookies, categories } = props;
const main = process.env.ROOT_CATEGORIES.split(',');
useEffect(() => {
    if (cookies.get('roles')) {
        const roles = cookies.get('roles');
        setIsAdmin(!!roles.includes('ROLE_ADMIN') || roles.includes('ROLE_SUPERADMIN'));
    }
});
const toggleProductsMenu = (isOpen) => {
    if (event.type === 'keydown' && (event.key === 'Tab' || event.key === 'Shift')) {
        return;
    }
    setIsOpenProductsMenu(isOpen);
};
const toggleServicesMenu = (isOpen) => {
    if (event.type === 'keydown' && (event.key === 'Tab' || event.key === 'Shift')) {
        return;
    }
    setIsOpenServicesMenu(isOpen);
};
return (
    <MenuList className={styles.navMobile} style={{ padding: '0 10px 0 0' }}>
        <MenuItem disableGutters>
            <Link to="/" activeStyle={activeStyle}>Home</Link>
        </MenuItem>
        <MenuItem disableGutters>
            <Link to="/search" activeStyle={activeStyle}>Search</Link>
        </MenuItem>
        <MenuItem
            onMouseEnter={() => toggleProductsMenu(true)}
            onMouseLeave={() => toggleProductsMenu(false)}
            className={styles.overrideItem}
            disableGutters
        >
            <NavDrawer
                type={main[0]}
                open={isOpenProductsMenu}
                categories={categories}
                toggleMenu={toggleProductsMenu}
            />
            <Link to="/" onClick={(event) => event.preventDefault}>
                <div className={styles.itemWrap}>
                    {main[0]}
                    <ExpandMore />
                </div>
            </Link>
        </MenuItem>
        <MenuItem
            onMouseEnter={() => toggleServicesMenu(true)}
            onMouseLeave={() => toggleServicesMenu(false)}
            className={styles.overrideItem}
            disableGutters
        >
            <NavDrawer
                type={main[1]}
                open={isOpenServicesMenu}
                categories={categories}
                toggleMenu={toggleServicesMenu}
            />
            <Link to="/" onClick={(event) => event.preventDefault}>
                <div className={styles.itemWrap}>
                    {main[1]}
                    <ExpandMore />
                </div>
            </Link>
        </MenuItem>
        {isAdmin ?
            (
                <MenuItem disableGutters>
                    <Link to="/admin" activeStyle={activeStyle}>Admin</Link>
                </MenuItem>
            ) : null}
    </MenuList>
);
};

NavMobile.propTypes = {
    cookies: PropTypes.instanceOf(Cookies).isRequired,
   categories: PropTypes.array.isRequired,
};

 export default withCookies(NavMobile);

但是,如果我尝试访问子组件中的道具,如下所示, toggleMenu function 将不在 output 中;

而且,当然,会抛出一个type error

export default function NavDrawer(props) {
 const {
    type,
    open,
    categories,
    toggleMenu,
 } = props;
 console.log('props drawer', props);

             <Drawer
            id={`parentDrawer-${type}`}
            onMouseEnter={() => setIsOpenSubDrawer(true)}
            onMouseLeave={() => setIsOpenSubDrawer(false)}
            className={classes.drawer}
            variant="temporary"
            open={open}
            close={toggleMenu(false)}

控制台输出

我错过了什么?

所以在我指出两种可能的解决方案之前,重要的是要注意您在父 function 调用中使用render方法,并且render方法仅用于 Class 函数,而不是无状态函数。

如果你想使用无状态 function,那么你应该使用return

查看文档中的差异

这里是截图:

无状态组件

类组件

现在进入解决方案, Stateless Functions不应该有方法,添加它们通常被认为是不好的做法。 我知道您想熟悉非类组件,但是混合使用两者并没有错,而且通常应该这样做。 如果你想添加方法,你应该使用Class Component并这样

class NavMobile extends Component {
  constructor(props) {
    super(props);   
    this.state = {
     // Empty for now
    }
  }


  toggleMenu = () => {
    // Your code
  }

  render() {
    return (
      // More code 

      <Navbar toggleMenu={this.toggleMenu} />

     // More code
    )
  }
}

它被认为是不好的做法的原因是因为每次调用组件时都会重新定义 function toggleMenu()

If you really want to go ahead with this, then you should declare the function outside of the component function so you declare the function only once and use the same reference.

您应该尝试以下方法:

const toggleMenu = (isOpen) => { ... };

并像这样在组件中调用它

const NavMobile = (props) => {
  return (
    // Your code
    <NavBar toggleMenu={toggleMenu.bind(null, propsYouWantToPass} />
  )
}

最后,您似乎正在寻找 function 内部的事件 object 例如(event.type === 'keydown') ,但没有传递此类事件,因为在子组件NavBar中您使用false参数调用它。

让我知道它是否有帮助。

PS:我一开始关于renderreturn的评论是针对您进行编辑之前的代码的。 我还是留在这里留给后人吧。

toggleProductsMenu 和 toggleServicesMenu 中的事件 object 未定义。

暂无
暂无

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

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