我和React和Redux一起工作。我希望Redux存储客户端信息(视口尺寸、浏览器名称和版本、操作系统等)。我已经设置了减速器和操作,并将所有状态映射到
<App />
组件的道具。内部
<应用程序/>
组件有一个
<Header />
<NavigationBar />
组件。
<导航栏/>
然后映射要渲染的道具
<NavigationItems />
然后生成以下导航栏:
Home | About us | Apply | News | Login
但是由于里面的道具映射
<应用程序/>
组件,每次用户调整视口大小时,Redux存储区内的状态都会发生更改,从而导致内部出现道具
<应用程序/>
Home | Home | About us | Apply | News | Login
或者
About us | Home | About us | Apply | News | Login
<导航栏/>
为了更好地说明这一点,我加入了代码结构:
Store (contains client info)
---> <App /> (map states, dispatchers from store to props)
---> <Header /> (functional component acts as container, pass navigation settings as props down to <NavigationBar />)
---> <NavigationBar /> (receives props from <Header /> and renders <NavigationItems /> component with props from <Header /> using map() function)
---> <NavigationItems /> (renders navigation items based on the props)
export const tUpdateViewport = 'updateViewport'
根操作.js
import { tUpdateViewport } from './rootTypes';
export const aUpdateViewport = () => ({type: tUpdateViewport })
根还原剂.js
(定义app reducer并将其与其他应用程序合并)
import { tUpdateViewport } from './rootTypes';
import { combineReducers } from 'redux';
const appStates = {
viewportWidth: document.documentElement.clientWidth,
viewportHeight: document.documentElement.clientHeight,
};
const appReducer = (states = appStates, action) => {
switch(action.type) {
case tUpdateViewport:
return {
...states,
viewportWidth: document.documentElement.clientWidth,
viewportHeight: document.documentElement.clientHeight,
};
default:
return states;
}
};
export default combineReducers({
app: appReducer,
})
应用程序.js
<
组件和渲染
<
)
import React from 'react';
import Header from './components/container/header/Header';
import * as actions from './rootActions';
import { connect } from 'react-redux';
const mapStatesToProps = states => ({
browserInfo: states.app
});
class App extends React.Component {
componentDidMount = () => {
window.addEventListener('resize', this.props.aUpdateViewport, false);
};
componentWillUnmount = () => {
window.removeEventListener('resize', this.props.aUpdateViewport, false);
};
render = () => {
return (
<Header />
);
};
}
export default connect(mapStatesToProps, actions)(App)
标题.js
(定义
<标题/>
组件和渲染
<导航栏/>
import React from 'react';
import NavigationBar from '../../presentational/header/NavigationBar';
import { Container, Grid, Row, Col } from '../../../css/Grid.css';
import { Header as Navigator } from '../../../css/Layout.css';
import logo from '../../../media/images/logo.png';
const Header = props => {
return (
<Navigator>
<Container>
<header>
<Grid>
<Row>
<Col>
<a href="#"><img src={logo} alt="CKY-UK Logo" /></a>
</Col>
<Col stretchWidth>
<Grid>
<Row stretchHeight alignEnd="md" alignMiddle="md">
<NavigationBar settings={{
items:
[
{
title: 'Home',
link: '/'
},
{
title: 'About us',
dropdownHierarchy: 'parents',
icons: [{
title: 'chevron-down',
iconPos: 'afterText'
}],
items: [{
title: 'Leadership Team',
link: '#leadership-team'
},
{
title: 'Star players',
link: '#star-players'
}]
},
{
title: 'Apply',
link: '#apply'
},
{
title: 'News',
link: '#news'
},
{
title: 'Login',
link: '#login',
icons: [{
title: 'sign-in-alt',
iconPos: 'beforeText'
}],
}
]
}} />
</Row>
</Grid>
</Col>
</Row>
</Grid>
</header>
</Container>
</Navigator>
);
};
export default Header
导航栏.js
(定义
<导航栏/>
要渲染的组件和贴图道具
<导航项目/>
组件)
import React from 'react';
import NavigationItems from './NavigationItems';
import { uniqID } from '../../../common/Functions';
import { Row } from '../../../css/Grid.css';
const NavigationBar = props => {
const settings = props.settings;
return (
<nav>
<ul>
<Row>
{settings.items.map((contents, index) =>
<NavigationItems settings={{...contents}} isDropdown={contents.items ? true : false} key={uniqID()} />
)}
</Row>
</ul>
</nav>
);
};
export default NavigationBar
(定义
<
并渲染导航栏)
import React from 'react';
import { uniqID } from '../../../common/Functions';
import { NavLi, NavItem, Dropdown } from '../../../css/Navigation.css';
import { Icon } from '../../../css/Common.css';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
class NavigationItems extends React.Component {
constructor(props) {
super(props);
this.state = {
dropdownOpened: false,
navLiWidth: null,
navLiHeight: null
}
}
handleClick = e => {
e.preventDefault();
this.setState(prevState => ({
dropdownOpened: !prevState.dropdownOpened
}));
};
handleClickOutside = e => {
const target = e.target;
if (!this.NavLi.contains(target)) {
this.setState({
dropdownOpened: false
})
}
}
componentDidMount = () => {
const navLiWidth = this.NavLi.clientWidth,
navLiHeight = this.NavLi.clientHeight;
this.setState({
navLiWidth: navLiWidth,
navLiHeight: navLiHeight
});
document.addEventListener('click', this.handleClickOutside, false);
}
componentWillUnmount = () => {
document.removeEventListener('click', this.handleClickOutside, false);
}
render = () => {
const settings = this.props.settings,
isDropdown = this.props.isDropdown
return (
<NavLi isDropdown={isDropdown} innerRef={x => this.NavLi = x}>
<NavItem href={settings.link || '#'} onClick={isDropdown ? this.handleClick : null}>
{settings.icons && settings.icons.filter(contents => contents.iconPos === 'beforeText').map(contents =>
<Icon beforeText key={uniqID()}><FontAwesomeIcon icon={contents.title} fixedWidth /></Icon>
)}
{settings.title}
{settings.icons && settings.icons.filter(contents => contents.iconPos === 'afterText').map(contents =>
<Icon afterText key={uniqID()}><FontAwesomeIcon icon={contents.title} fixedWidth /></Icon>
)}
</NavItem>
{isDropdown &&
<Dropdown hierarchy={settings.dropdownHierarchy} opened={this.state.dropdownOpened} topPos={this.state.navLiHeight} leftPos={this.state.navLiWidth} desPos={10} startPos={50}>
{settings.items.map(contents =>
<NavigationItems settings={{...contents}} isDropdown={contents.items ? true : false} key={uniqID()} />
)}
</Dropdown>
}
</NavLi>
);
};
};
export default NavigationItems
我怎样才能解决这个问题?曾在谷歌上搜索过地图问题,但没有找到想要的结果。任何帮助都将不胜感激。