[英]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.