简体   繁体   English

传递了一个 function 作为道具,但它没有在 React 的子组件中执行

[英]Passed a function as props but it's not executing in child component in React

I am using semantic-react-ui to make a menu.我正在使用语义反应用户界面来制作菜单。 To leverage the active state functionality.利用活动的 state 功能。 When you're on a link it gets focus or underline in this case.在这种情况下,当您在链接上时,它会获得焦点或下划线。 However with my implementation I am passing it down the function to a child component as props.但是,通过我的实现,我将 function 作为道具传递给子组件。 See below...见下文...

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

Should I move the state down into the HOC?我应该将 state 移到 HOC 中吗? I am not getting errors so I'm stumped.我没有收到错误,所以我很难过。

UPDATE 10/25/2019 2019 年 10 月 25 日更新

Decided to just add the latest feedback(error) from console and updated code:决定从控制台添加最新的反馈(错误)和更新的代码:

Now when I click the /profile link/route I get this error:现在,当我单击/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

This is the HOC:这是 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);

This is the class component:这是 class 组件:

    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 10/25/19 9:21PM EST更新 2019 年 10 月 25 日美国东部标准时间晚上 9:21

I updated my my HOC:我更新了我的 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);

This is my component:这是我的组件:

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

But now getting this error:但现在得到这个错误:

在此处输入图像描述

How can that be if I am passing the function in correctly?如果我正确传递 function 怎么办?

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

And using it correctly?并正确使用它?

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

UPDATE 10/26/19 2019 年 10 月 26 日更新

So I know this is working because of the console out put...所以我知道这是因为控制台输出...

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

here:这里:

在此处输入图像描述

And in my parent component I added a default state of:在我的父组件中,我添加了一个默认的 state :

 state = {activeItem: 'home'}

Which is rendering correctly:哪个正确渲染:

在此处输入图像描述

But I am still getting the error:但我仍然收到错误:

在此处输入图像描述

And for good measure here are my components as they are in the Parent:为了更好地衡量,这里是我的组件,因为它们在父级中:

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

Should I be passing in the parameter in the child component?我应该在子组件中传递参数吗?

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

First of all your handleClick will cause an error when setting a state because of the context of this .首先,由于this的上下文,您的 handleClick 在设置 state 时会导致错误。 So i suggest you either bind it in constructor or change it to an arrow function like this -所以我建议你要么在构造函数中绑定它,要么像这样将其更改为箭头 function -

handleItemClick = (e) => {}

Now, I have used semantic-ui-react for couple of projects and there click events runs a bit differently.现在,我在几个项目中使用了 semantic-ui-react,点击事件的运行方式略有不同。 According to the docs -根据文档 -

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.

So change your onClick to onClick={handleItemClick} then因此,将您的 onClick 更改为onClick={handleItemClick}然后

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

I hope this helps you.我希望这可以帮助你。

UPDATE: Your latest error is because of <a> tags inside Link.更新:您的最新错误是由于链接中的<a>标记。 Link from react-router is like an tag and we know react-router的链接就像一个标签,我们知道

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

is invalid HTML.无效 HTML。 You can refer to this question for more information Link cannot appear as a descendant of a link .您可以参考此问题以获取更多信息链接不能作为链接的后代出现

And to solve your errors simply remove tags inside tags.要解决您的错误,只需删除标签内的标签。

UPDATE: -更新: -

The latest error is because you are passing name in your handleItemClick最新的错误是因为您在 handleItemClick 中传递名称

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

Can you try binding your method in constructor as您可以尝试在构造函数中将您的方法绑定为

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

} }

Hope it helps希望能帮助到你

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

相关问题 为什么 props 没有传递给子组件 Route React? - Why is props not passed to child component Route React? 为什么反应道具未定义传递给子组件? - why react props are passed undefined to the child component? 2个具有地图功能的道具传递给子组件 - 2 Props passed to Child Component with a Map Function 如何测试 function 在 React 中作为道具传递给孩子? - How to test a function passed as props to child in React? 当子组件尝试调用传递的函数时,在React中获取typeError提示this.props不是函数 - Getting a typeError in React saying this.props is not a function when child component tries to call passed function 传递给 react-table 第 2 页以上的子组件的错​​误道具 - Incorrect props passed to child component on pages 2+ of react-table 通过新道具时,反应子组件状态不会更新 - React child component state not updating when new props are passed React:告诉子组件“重新初始化”,即使传递的 props 相同 - React: Tell child component to “reinitialize,” even when the passed props are the same React JS 道具不会在父重新渲染时传递给子组件 - React JS props are not passed to child component on parent rerender 子组件无法访问通过React Route传递的道具 - Props passed through React Route cant be accessed by child component
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM