作为道具传递了一个函数,但未在React

时间:2019-10-25 03:38:22

标签: javascript reactjs react-props

我正在使用语义反应用户界面制作menu.以利用活动状态功能。在这种情况下,当您使用链接时,它会成为焦点或下划线。但是,在实现过程中,我将其作为道具传递给了子组件。见下文...

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吗?我没有收到错误,所以很困惑。

更新10/25/2019

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

现在,当我单击/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>
  )
 }
}

UPDATE EST 10/25/19 9:21 PM

我更新了我的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>
  )
 }
}

但是现在出现此错误:

enter image description here

如果我正确传递了函数怎么办?

        <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>
}

更新19/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>
  }

此处:

enter image description here

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

 state = {activeItem: 'home'}

正确渲染的是

enter image description here

但是我仍然收到错误:

enter image description here

在很大程度上,这是我在父级中使用的组件:

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

2 个答案:

答案 0 :(得分:1)

首先,由于this的上下文,您的handleClick会在设置状态时导致错误。因此,我建议您将其绑定到构造函数中,或将其更改为这样的箭头函数-

handleItemClick = (e) => {}

现在,我已将语义UI反应用于几个项目,并且单击事件的运行方式略有不同。根据文档-

Called on click. When passed, the component will render as an `a`
tag by default instead of a `div`.

onClick(event: SyntheticEvent, data: object)
event
React's original SyntheticEvent.
data
All props.

因此将onClick更改为onClick={handleItemClick},然后

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

希望对您有帮助。

更新:您的最新错误是由于Link中的<a>标签引起的。来自react-router的链接就像一个标签,我们知道

<a href="1">
    <a href="2"></a>
</a>

是无效的HTML。您可以参考此问题以获取更多信息Link cannot appear as a descendant of a link

要解决您的错误,只需删除标签内的标签即可。

更新:-

最新错误是因为您在handleItemClick中传递名称

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

答案 1 :(得分:1)

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

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

}

希望有帮助