首页 > 解决方案 > 传递了一个函数作为道具,但它没有在 React 的子组件中执行

问题描述

我正在使用语义反应用户界面来制作菜单。利用活动状态功能。在这种情况下,当您在链接上时,它会获得焦点或下划线。但是,通过我的实现,我将它作为道具传递给子组件。见下文...

class DesktopContainer extends Component {
 state = {}

 handleItemClick(event) {
  var { name } = event.target;
  this.setState({
   activeItem: name
  })
 }


 render() {
  const { GenericHeadingComponent, children, getWidth, isLoggedIn, logOutUser } = this.props

  const { fixed, activeItem } = this.state

  return (
   <Responsive getWidth={getWidth} minWidth={Responsive.onlyTablet.minWidth}>

        <GenericIsUserLoggedInLink
         isHomeButton={true}
         key="1"
         name='home'
         active={activeItem === 'home'}
         handleItemClick={this.handleItemClick} /* is this correct */
         mobile={false}
        />

        <GenericIsUserLoggedInLink
         isLoggedIn={isLoggedIn}
         route="/profile"
         anchorText="Profile"
         key="2"
         name='profile'
         active={activeItem === 'profile'}
         handleItemClick={this.handleItemClick} /* is this correct */
         mobile={false}
        />

        <GenericIsUserLoggedInLink
         isLoggedIn={isLoggedIn}
         route="/dashboard"
         anchorText="Dashboard"
         key="3"
         name='dashboard'
         active={activeItem === 'dashboard'}
         handleItemClick={this.handleItemClick}  /* is this correct */
         mobile={false}

        />


        <Menu.Item position='right'>
         <Button inverted={!fixed}>
          <GenericIsUserLoggedInLink
           route="/login"
           isLoggedIn={isLoggedIn}
           logOutUser={logOutUser}
           key="4" />
         </Button>
         <Button inverted={!fixed} primary={fixed} style={{ marginLeft: '0.5em' }}>
          <Link href="/register">
           <a>Register</a>
          </Link>
         </Button>
        </Menu.Item>
       </Container>
      </Menu>
      <GenericHeadingComponent />
     </Segment>
    </Visibility>

    {children}
   </Responsive>
  )
 }
}

DesktopContainer.propTypes = {
 children: PropTypes.node,
}


LayoutComponent.propTypes = {
 children: PropTypes.node,
}
     var comparator;
const GenericIsUserLoggedInLink = React.memo(({ isHomeButton, isLoggedIn, logOutUser, route, anchorText, mobile, active, handleItemClick }) => {
 comparator = (prevProps, nextProps) => {
  if (prevProps.isHomeButton !== nextProps.setProps.isHomeButton) {
   return true;
  }
  if (prevProps.isLoggedIn !== nextProps.setProps.route) {
   return true;
  }
  if (prevProps.anchorText !== nextProps.setProps.anchorText) {
   return true;
  }
  if (prevProps.active !== nextProps.setProps.active) {
   return true;
  }
  return false;
 }
if (isHomeButton) {
 return <Menu.Item active={active} onClick={() => handleItemClick}><Link href="/"><a>Home</a></Link></Menu.Item>
}
 if (isLoggedIn) {
  if (anchorText === undefined) {
   return <Link href="/"><a onClick={() => logOutUser()}>Log out!</a></Link>
  }
  else if (anchorText && mobile) {
   console.log("active 1 ", active);

   return <Menu.Item active={active}><Link href={route}><a >{anchorText}</a></Link></Menu.Item>
  }
  else if ((anchorText) && (!(mobile))) {
   console.log("mobile 2 ", mobile);
   return <Menu.Item active={active} onClick={() => handleItemClick}><Link href={route}><a >{anchorText}</a></Link></Menu.Item>
  }

  else if (anchorText) {
   return <Link href={route}><a >{anchorText}</a></Link>
  }
 } else {
  if (route === "/login") {
   return <Link href="/login"><a >Log in!</a></Link>
  }
  return  null
 }
}, comparator);

我应该将状态下移到 HOC 吗?我没有收到错误,所以我很难过。

2019 年 10 月 25 日更新

决定从控制台添加最新的反馈(错误)和更新的代码:

现在,当我单击/profile链接/路由时,出现此错误:

index.js:1 Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>.
    in a (created by Link)
    in Link
    in a (created by MenuItem)
    in MenuItem
    in Unknown (created by DesktopContainer)
    in div (created by Container)
    in Container (created by DesktopContainer)
    in div (created by Menu)
    in Menu (created by DesktopContainer)
    in div (created by Segment)
    in Segment (created by DesktopContainer)
    in div (created by Visibility)
    in RefFindNode (created by Ref)
    in Ref (created by Visibility)
    in Visibility (created by DesktopContainer)
    in div (created by Responsive)
    in Responsive (created by DesktopContainer)
    in DesktopContainer (created by LayoutComponent)
    in LayoutComponent (created by Connect(LayoutComponent))
    in Connect(LayoutComponent) (created by ProfilePage)
    in ProfilePage (created by Profile)
    in Profile (created by Connect(Profile))
    in Connect(Profile) (created by Auth)
    in Auth (created by MyApp)
    in PersistGate (created by MyApp)
    in Provider (created by MyApp)
    in MyApp (created by AppWithRedux)
    in AppWithRedux
    in Suspense (created by AppContainer)
    in Container (created by AppContainer)
    in AppContainer

这是 HOC:

var comparator;
const GenericIsUserLoggedInLink = React.memo(({ isHomeButton, isLoggedIn, logOutUser, route, anchorText, mobile,  activeItem, name, active, handleItemClick }) => {
 comparator = (prevProps, nextProps) => {
  if (prevProps.isHomeButton !== nextProps.setProps.isHomeButton) {
   return true;
  }
  if (prevProps.isLoggedIn !== nextProps.setProps.isLoggedIn) {
   return true;
  }
  if (prevProps.anchorText !== nextProps.setProps.anchorText) {
   return true;
  }
  if (prevProps.active !== nextProps.setProps.active) {
   return true;
  }
  if (prevProps.mobile !== nextProps.setProps.mobile) {
   return true;
  }
  if (prevProps.activeItem !== nextProps.setProps.activeItem) {
   return true;
  }
  if (prevProps.active !== nextProps.setProps.active) {
   return true;
  }
  return false;
 }
if (isHomeButton) {
 console.log("active ", active);
 return <Menu.Item name={name} active={activeItem === name} onClick={handleItemClick}><Link href="/"><a>Home</a></Link></Menu.Item>
}
 if (isLoggedIn) {
  if (anchorText === undefined) {
   return <Link href="/"><a onClick={() => logOutUser()}>Log out!</a></Link>
  }
  else if (anchorText && mobile) {
   console.log("active 1 ", active);

   console.log("mobile 1 ", mobile);
   return <Menu.Item active={active}><Link href={route}><a >{anchorText}</a></Link></Menu.Item>
  }
  else if ((anchorText) && (!(mobile))) {
   console.log("mobile 2 ", mobile);
   return <Menu.Item name={name} active={activeItem === name} onClick={handleItemClick}><Link href={route}><a >{anchorText}</a></Link></Menu.Item>
  }

  else if (anchorText) {
   return <Link href={route}><a >{anchorText}</a></Link>
  }
 } else {
  if (route === "/login") {
   return <Link href="/login"><a >Log in!</a></Link>
  }
  return  null
 }
}, comparator);

这是类组件:

    class DesktopContainer extends Component {
     state = {}

     handleItemClick = (e, { name }) => this.setState({ activeItem: name })

     render() {
      const { GenericHeadingComponent, children, getWidth, isLoggedIn, logOutUser } = this.props

      const { fixed, activeItem } = this.state

    return (
   <Responsive getWidth={getWidth} minWidth={Responsive.onlyTablet.minWidth}>
    <Visibility
     once={false}
     onBottomPassed={this.showFixedMenu}
     onBottomPassedReverse={this.hideFixedMenu}
    >
     <Segment
      inverted
      textAlign='center'
      style={{ minHeight: 700, padding: '1em 0em' }}
      vertical
     >
      <Menu
       fixed={fixed ? 'top' : null}
       inverted={!fixed}
       pointing={!fixed}
       secondary={!fixed}
       size='large'
      >
       <Container>

        <GenericIsUserLoggedInLink
         isHomeButton={true}
         key="1"
         name='home'
         active={activeItem === 'home'}
         handleItemClick={this.handleItemClick}
         mobile={false}
        />

        <GenericIsUserLoggedInLink
         isLoggedIn={isLoggedIn}
         route="/profile"
         anchorText="Profile"
         key="2"
         name='profile'
         active={activeItem === 'profile'}
         handleItemClick={this.handleItemClick}
         mobile={false}
        />

        <GenericIsUserLoggedInLink
         isLoggedIn={isLoggedIn}
         route="/dashboard"
         anchorText="Dashboard"
         key="3"
         name='dashboard'
         active={activeItem === 'dashboard'}
         handleItemClick={this.handleItemClick}
         mobile={false}

        />

        <Menu.Item position='right'>
         <Button inverted={!fixed}>
          <GenericIsUserLoggedInLink
           route="/login"
           isLoggedIn={isLoggedIn}
           logOutUser={logOutUser}
           key="4" />
         </Button>
         <Button inverted={!fixed} primary={fixed} style={{ marginLeft: '0.5em' }}>
          <Link href="/register">
           <a>Register</a>
          </Link>
         </Button>
        </Menu.Item>
       </Container>
      </Menu>
      <GenericHeadingComponent />
     </Segment>
    </Visibility>

    {children}
   </Responsive>
  )
 }
}

更新 2019 年 10 月 25 日美国东部标准时间晚上 9:21

我更新了我的 HOC:

var comparator;
const GenericIsUserLoggedInLink = React.memo(({ isHomeButton, isLoggedIn, logOutUser, route, anchorText, mobile,  activeItem, name, handleItemClick }) => {

 comparator = (prevProps, nextProps) => {

  if (prevProps.isHomeButton !== nextProps.setProps.isHomeButton) {
   return true;
  }
  if (prevProps.isLoggedIn !== nextProps.setProps.isLoggedIn) {
   return true;
  }
  if (prevProps.mobile !== nextProps.setProps.mobile) {
   return true;
  }
  if (prevProps.active !== nextProps.setProps.active) {
   return true;
  }
  return false;
 }
if (isHomeButton) {
 return <Link href="/"><Menu.Item name={name} active={activeItem === name} onClick={()=>handleItemClick(name)}></Menu.Item></Link>
}
 if (isLoggedIn) {
  if (anchorText === undefined) {
   return <Link href="/"><a onClick={() => logOutUser()}>Log out!</a></Link>
  }
  else if (anchorText && mobile) {

   return <Link href={route}><Menu.Item name={name} active={activeItem === name}>{anchorText}</Menu.Item></Link>
  }
  else if ((!(mobile))) {
   console.log("mobile 2 ", mobile);
   return <Link href={route}><Menu.Item name={name} active={activeItem === name} onClick={() => handleItemClick(name)}></Menu.Item></Link>
  }

  else if (anchorText) {
   return <Link href={route}><a>{anchorText}</a></Link>
  }
 } else {
  if (route === "/login") {
   return <Link href="/login"><a>Log in!</a></Link>
  }
  return  null
 }
}, comparator);

这是我的组件:

class DesktopContainer extends Component {
 state = {}

 hideFixedMenu = () => this.setState({ fixed: false })
 showFixedMenu = () => this.setState({ fixed: true })
 handleItemClick = (e, { name }) => this.setState({ activeItem: name })


 logOutUser = () => {
  const { logOutUser } = this.props
  logOutUser()
 }

 render() {
  const { GenericHeadingComponent, children, getWidth, isLoggedIn, logOutUser } = this.props


  const { fixed, activeItem } = this.state

  return (
   <Responsive getWidth={getWidth} minWidth={Responsive.onlyTablet.minWidth}>
    <Visibility
     once={false}
     onBottomPassed={this.showFixedMenu}
     onBottomPassedReverse={this.hideFixedMenu}
    >
     <Segment
      inverted
      textAlign='center'
      style={{ minHeight: 700, padding: '1em 0em' }}
      vertical
     >
      <Menu
       fixed={fixed ? 'top' : null}
       inverted={!fixed}
       pointing={!fixed}
       secondary={!fixed}
       size='large'
      >
       <Container>

        <GenericIsUserLoggedInLink
         isHomeButton={true}
         key="1"
         name='home'
         activeItem={activeItem}
         handleItemClick={this.handleItemClick}
         mobile={false}
        />

        <GenericIsUserLoggedInLink
         isLoggedIn={isLoggedIn}
         route="/profile"
         anchorText="Profile"
         key="2"
         name='profile'
         activeItem={activeItem}
         handleItemClick={this.handleItemClick}
         mobile={false}
        />

        <GenericIsUserLoggedInLink
         isLoggedIn={isLoggedIn}
         route="/dashboard"
         anchorText="Dashboard"
         key="3"
         name='dashboard'
         activeItem={activeItem}
         handleItemClick={this.handleItemClick}
         mobile={false}
        />


        <Menu.Item position='right'>
         <Button inverted={!fixed}>
          <GenericIsUserLoggedInLink
           route="/login"
           isLoggedIn={isLoggedIn}
           logOutUser={logOutUser}
           key="4" />
         </Button>
         <Button inverted={!fixed} primary={fixed} style={{ marginLeft: '0.5em' }}>
          <Link href="/register">
           <a>Register</a>
          </Link>
         </Button>
        </Menu.Item>
       </Container>
      </Menu>
      <GenericHeadingComponent />
     </Segment>
    </Visibility>

    {children}
   </Responsive>
  )
 }
}

但现在得到这个错误:

在此处输入图像描述

如果我正确地传递函数,那怎么可能?

        <GenericIsUserLoggedInLink
         isHomeButton={true}
         key="1"
         name='home'
         activeItem={activeItem}
         handleItemClick={this.handleItemClick} /* no ? */
         mobile={false}
        />

并正确使用它?

if (isHomeButton) {
 return <Link href="/"><Menu.Item name={name} active={activeItem === name} onClick={()=>handleItemClick(name)}></Menu.Item></Link>
}

2019 年 10 月 26 日更新

所以我知道这是因为控制台输出...

  else if ((!(mobile))) {
   console.log("name 1", name);
   console.log("activeItem 1", activeItem);
   return <Link href={route}><Menu.Item name={name} active={activeItem === name} onClick={handleItemClick}></Menu.Item></Link>
  }

这里:

在此处输入图像描述

在我的父组件中,我添加了一个默认状态:

 state = {activeItem: 'home'}

哪个正确渲染:

在此处输入图像描述

但我仍然收到错误:

在此处输入图像描述

为了更好地衡量,这里是我的组件,因为它们在父级中:

        <GenericIsUserLoggedInLink
         isHomeButton={true}
         key="1"
         name='home'
         activeItem={activeItem}
         handleItemClick={this.handleItemClick}
         mobile={false}
        />

        <GenericIsUserLoggedInLink
         isLoggedIn={isLoggedIn}
         route="/profile"
         anchorText="Profile"
         key="2"
         name='profile'
         activeItem={activeItem}
         handleItemClick={this.handleItemClick}
         mobile={false}
        />

        <GenericIsUserLoggedInLink
         isLoggedIn={isLoggedIn}
         route="/dashboard"
         anchorText="Dashboard"
         key="3"
         name='dashboard'
         activeItem={activeItem}
         handleItemClick={this.handleItemClick}
         mobile={false}
        />

我应该在子组件中传递参数吗?

 return <Link href="/"><Menu.Item name={name} active={activeItem === name} onClick={()=>handleItemClick(name)}></Menu.Item></Link>

标签: javascriptreactjsreact-props

解决方案


您可以尝试在构造函数中将您的方法绑定为

class DesktopContainer extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.handleItemClick = this.handleItemClick.bind(this);
  }
  // remaining code

}

希望能帮助到你


推荐阅读