道具更改时map()引起的意外渲染

时间:2018-08-31 03:24:08

标签: reactjs redux

我正在使用React和Redux。我希望Redux存储客户端信息(视口尺寸,浏览器名称和版本,操作系统等)。我已经设置了化简器和动作,并将所有状态映射到<App />组件的道具。在<App />组件内部有一个<Header />组件,可将道具传递到<NavigationBar />组件。 <NavigationBar />然后将道具映射到渲染<NavigationItems />,然后生成以下导航栏:

Home  | About us | Apply | News | Login

但是,由于<App />组件内的props映射,每次用户调整视口大小时,Redux存储内的状态都会发生变化,<App />内的props也会发生变化,当然,React也要重新渲染整个导航栏会产生以下意外行为:

Home | Home | About us | Apply | News | Login

About us | Home | About us | Apply | News | Login

简而言之,<NavigationBar />返回的项目过多。 我已经包括了代码结构以便更好地说明:

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)

我还提供了代码,以防万一有人需要它:

rootTypes.js (定义操作类型)

export const tUpdateViewport = 'updateViewport'

rootActions.js (定义调度程序)

import { tUpdateViewport } from './rootTypes';

export const aUpdateViewport = () => ({type: tUpdateViewport })

rootReducer.js (定义应用程序简化程序并将其与其他程序组合)

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,
})

App.js (定义{{​​1}}组件并呈现<App />

<Header />

Header.js (定义{{​​1}}组件并呈现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) 组件)

<Header />

NavigationBar.js (定义{{​​1}}组件并映射道具以渲染<NavigationBar />组件)

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

NavigationItems.js (定义{{​​1}}并呈现导航栏)

<NavigationBar />

我该如何解决?用谷歌搜索地图问题,但没有找到想要的结果。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

我猜uniqID只是一个随机数生成器?

key prop特别存在是随机的。将其更改为每个循环一致且唯一的值,例如title,这很可能会解决您的问题。