我将应用程序的主导航菜单作为使用connect连接到redux存储的react组件。菜单组件也分为几部分,在部分内部有主题。菜单具有状态变量(在商店中),用于指示菜单是否必须折叠显示。我通过相应的操作更改了状态,我看到菜单外观发生了变化,但是各部分的外观没有变化。我将collapse的值作为道具传递,但是如果没有调用要相应渲染的菜单部分的render函数。
这是Menu和MenuSection组件的代码:
Menus.jsx
// modules/menu/components/Menu.jsx
import React from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import * as actions from '../actions'
import { MODULE_NAME } from '../constants'
import MenuSection from './MenuSection'
const propTypes = {
menu: PropTypes.shape({
sections: PropTypes.array,
collapsed: PropTypes.bool,
activeSection: PropTypes.number,
inflatedSection: PropTypes.number,
activeTopic: PropTypes.number,
}).isRequired,
actions: PropTypes.shape({
toggle: PropTypes.func,
activateSection: PropTypes.func,
toggleSection: PropTypes.func,
}).isRequired,
}
class Menu extends React.Component {
constructor(props) {
super(props)
}
toggleMenu = () => this.props.actions.toggleMenu()
activateSection = (s, t) => this.props.actions.activateSection(s, t)
toggleSection = (s) => this.props.actions.toggleSection(s)
render() {
const collapsed = this.props.menu.collapsed
const sections = this.props.menu.sections.map((section, i) => {
const {
disabled = false,
icon, text,
route = { to: '#' },
topics = [],
} = section
const active = this.props.menu.activeSection === i
const inflated = this.props.menu.inflatedSection === i
return (
<MenuSection
key={i}
idx={i}
to={route.to}
{...{
icon,
text,
topics,
disabled,
active,
inflated,
}}
activate={this.activateSection}
toggle={this.toggleSection}
activeTopic={this.props.menu.activeTopic}
collapsed={collapsed}
/>
)
})
const classes = classNames('menu', { collapsed: collapsed })
const size = collapsed ? 'small' : 'big'
return (
<nav className={classes}>
<img src={`${process.env.PUBLIC_URL}/imgs/logo-${size}.png`} />
<ul>
{sections}
</ul>
</nav>
)
}
}
Menu.propTypes = propTypes
const mapStateToProps = state => ({ [MODULE_NAME]: state.menu })
const mapDispatchToProps = dispatch => (
{ actions: bindActionCreators(actions, dispatch) }
)
export default connect(mapStateToProps, mapDispatchToProps)(Menu)
MenuSection.jsx
// modules/menu/components/MenuSection.jsx
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { NavLink, withRouter } from 'react-router-dom'
import classNames from 'classnames'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faCaretDown, faCaretUp } from '@fortawesome/free-solid-svg-icons'
import MenuTopic from './MenuTopic'
const propTypes = {
idx: PropTypes.number.isRequired,
to: PropTypes.oneOfType([PropTypes.func, PropTypes.string]).isRequired,
icon: PropTypes.object.isRequired,
text: PropTypes.string.isRequired,
topics: PropTypes.arrayOf(PropTypes.object).isRequired,
activate: PropTypes.func.isRequired,
toggle: PropTypes.func.isRequired,
disabled: PropTypes.bool.isRequired,
active: PropTypes.bool.isRequired,
inflated: PropTypes.bool.isRequired,
activeTopic: PropTypes.number.isRequired,
collapsed: PropTypes.bool.isRequired
}
class MenuSection extends Component {
constructor(props) {
super(props)
this.onClick = this.onClick.bind(this)
this.activate = this.activate.bind(this)
}
shouldComponentUpdate(nextProps) {
const { active, inflated, activeTopic } = nextProps;
return (this.props.active !== active)
|| (this.props.inflated !== inflated) || (this.props.activeTopic !== activeTopic)
}
onClick() {
if (this.props.topics.length > 0) {
this.props.toggle(this.props.idx)
} else {
this.props.activate(this.props.idx, this.props.activeTopic)
}
}
activate(t) {
this.props.activate(this.props.idx, t)
}
render() {
const { idx, to, icon, text, topics, disabled, active, inflated, activeTopic, collapsed } = this.props
const items = (inflated ?
topics.map((topic, i) => (
<MenuTopic key={i} idx={i}
to={topic.route.to} text={topic.text} onClick={this.activate}
active={active && (activeTopic === i)} section={idx} />))
: []);
const classes = classNames({ disabled, active, inflated })
return (
<li className={classes}>
<NavLink to={to} activeClassName="active" onClick={this.onClick}>
<FontAwesomeIcon icon={icon} pull="left"/>
{!collapsed &&
<React.Fragment>
{' '}
{text}
{topics.length > 0 &&
<FontAwesomeIcon icon={ inflated ? faCaretUp : faCaretDown } pull="right" />
}
</React.Fragment>
}
</NavLink>
{(!collapsed) && inflated &&
<ul>
{items}
</ul>
}
</li>)
}
}
MenuSection.propTypes = propTypes
export default withRouter(MenuSection)
有什么想法吗?我对react-redux应用程序有些陌生,所以也许我错过了一些东西。
谢谢!
答案 0 :(得分:0)
它似乎不重新呈现的原因似乎是由于menuSection的shouldComponentUpdate。按照书面规定,仅在props.active,props.inflated或props.activeTopic更改时,才会重新渲染menuSection。因此,如果props.collapsed发生更改,但没有其他操作,则跳过渲染。