javascript - 传递了一个函数作为道具,但它没有在 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>
解决方案
您可以尝试在构造函数中将您的方法绑定为
class DesktopContainer extends Component {
constructor(props) {
super(props);
this.state = {};
this.handleItemClick = this.handleItemClick.bind(this);
}
// remaining code
}
希望能帮助到你
推荐阅读
- reactjs - 如何在 Storybook 中添加样式道具作为控件?
- docker - 无法在 AWS Lambda 容器中启动 Chromium,但可以在本地运行
- html - 如何在前两页使用(document.referrer)?
- google-sheets - 通过单个公式对每一行求和
- python - 我该如何解决这个问题?Python cantools关于id的关键错误
- git - 如何使分叉项目保持最新?
- python - “从 keras.utils 导入 to_categorical”中的错误
- reactjs - 移动 Draggable 时,列表顶部会出现很大的间隙,并且会奇怪地移动所有内容(React Beautiful DND)
- android - 使用光标时出现空指针异常
- html - 下拉菜单不是 100% 可见