簡體   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