我正在使用语义反应用户界面制作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>
)
}
}
但是现在出现此错误:
如果我正确传递了函数怎么办?
<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>
}
此处:
在我的父组件中,我添加了默认状态:
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>
答案 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
}
希望有帮助