如何避免在Redux状态更改后重新呈现组件?

时间:2019-01-15 22:52:34

标签: reactjs redux

我有一个用react和redux实现的通知弹出系统,每当我想发送带有消息的弹出窗口时,我都会调用redux动作,该动作将改变reducer的状态,并根据reducer的状态显示一个小吃栏。那是在包装子“路由器”组件的路由器组件中,它工作得很好,但是我遇到了用户体验问题,因为每次此通知显示时,它都会重新呈现包含图像的导航栏组件,您可以看到图像重新呈现通知出现时。

这对我来说很奇怪,因为通知操作没有更改包含图像的导航栏的状态,因此我认为不应重新渲染它,因为它没有更改其状态。有人可以给我一些提示吗?

我在redux thunk中使用了getState(),但我对其进行了更改,因为我发现不应使用它,因此不再使用它:https://blog.isquaredsoftware.com/2017/01/idiomatic-redux-thoughts-on-thunks-sagas-abstraction-and-reusability/

然后我重写了导航栏内的shouldComponentUpdate()函数,以验证道具与nextProps不同,因此它不会随着更改而重新渲染,但还没有运气!感谢您的帮助。

export const PrivateRoute = ({
  isAuthenticated,
  component: Component,
  userColors,
  messages,
  ...rest
}) => (
    <Route {...rest} component={(props) => (
      isAuthenticated ? (
        <div className="private-route" style={{
          backgroundColor: userColors.bkg ? userColors.bkg : 'linear-gradient(#3366CB, #204080)'
        }}>
          <NavComponent />

// The snackbar is open when messages.showing is true (this comes from redux store)

          <SimpleSnackbar message={messages.currentMessage} open={messages.showing}/>
          <Component {...props} />
        </div>
      ) : (
          <Redirect to="/" />
        )
    )} />
  );

我可以采取行动进行通知,以便messages.showing变为真,并在小吃栏上显示

this.props.notify(error);

在显示快餐栏之后,它重新渲染了不使用此状态的导航栏组件,并且与显示快餐栏的reducer无关,从而导致导航栏上的图像重新呈现,并且用户感觉不自然。

弹出窗口的操作是:

export const notify = (message) => ({
    type: 'NOTIFY',
    message
});

export const close = () => ({
    type: 'CLOSE'
});

减速器:

const messagesDefaultState = {
    currentMessage: '',
    showing: false
};

export default (state = messagesDefaultState, action) => {
    switch (action.type) {
      case 'NOTIFY':
        return {
            currentMessage: action.message,
            showing: true
        };
      case 'CLOSE':
        return messagesDefaultState;
      default:
        return state;
    }
}; 

并且有一个navbar组件连接到redux存储,并且包含一个化身,每次我从操作中调用通知时,该化身都闪烁。

    import React from 'react';
    import { connect } from 'react-redux';
    import { Link } from 'react-router-dom';
    import Avatar from 'react-avatar';
    import { startLogout } from '../actions/auth';
    import { startSetIdiom, startSetIdioms } from '../actions/idiom';

    export class NavComponent extends React.Component {
        constructor(props) {
            super(props);
        };

        shouldComponentUpdate(nextProps) {
            const differentPP = this.props.pp !== nextProps.pp;
            const differentName = this.props.name !== nextProps.name;
            return differentPP || differentName;
        }

        componentDidMount() {
            if(this.props.idiomData === ''){
                this.props.startSetIdioms();
                this.props.startSetIdiom('EN');
            }
        };

        burgerToggle = () => {
            let linksEl = document.querySelector('.narrowLinks');
            if (linksEl.style.display === 'block') {
                linksEl.style.display = 'none';
            } else {
                linksEl.style.display = 'block';
            }
        };

        render() {
            return (
                <nav>
                    <div className="navWide">
                        <div className="wideDiv">
                            <Link className="header__link header__link_home" to="/dashboard">
                                <i className="fas fa-home header__icon"></i>
                            </Link>
                            <Link className="header__link header__link_title show-for-desktop" to="/dashboard">{this.props.idiomData.navTitle && this.props.idiomData.navTitle || 'Main Menu'} </Link>
                            <div className="header__end">
                                <Link to="/changeProfilePic">

//This avatar is flickering everytime I call notify or close from the snackbar actions

<Avatar size="34px" name={this.props.name} src={this.props.pp} round={true}/></Link>    
                                <Link  className="nav__link" to="/profilePic">{this.props.idiomData.greeting  && this.props.idiomData.greeting || 'Hello, '} {this.props.name && this.props.name || ''}</Link>
                                <button className="nav__link">{this.props.idiom}</button>
                                <button className="nav__link" onClick={this.props.startLogout}>{this.props.idiomData.logOut || 'Logout'}</button>
                            </div>
                        </div>
                    </div>
                    <div className="navNarrow">
                        <Link className="header__link header__link_home" to="/dashboard">
                            <i className="fas fa-home header__icon"></i>
                        </Link>
                        <div onClick={this.burgerToggle}>
                            <i className="fa fa-bars fa-2x"></i>
                        </div>                  
                        <div className="narrowLinks">                   
                            <Link className="nav__link" to="/profilePic">{this.props.idiomData.greeting ? this.props.idiomData.greeting : 'Hello, ' } {this.props.name && this.props.name || ''}<Avatar size="34px" name={this.props.name} src={this.props.pp} round={true}/></Link>
                            <button className="nav__link">{this.props.idiom}</button>
                            <button className="nav__link" onClick={this.props.startLogout}>{this.props.idiomData.logOut || 'Logout'}</button>
                        </div>
                    </div>
                </nav>
            );
        };
    };

    const mapStateToProps = (state) => ({
        name: state.dash.userData.name,
        pp: state.dash.userData.profilePic,
        idiom: state.idiom.currentIdiom ? state.idiom.currentIdiom : 'EN',
        idiomData: state.idiom.idiomData.launchpad ? state.idiom.idiomData.launchpad : ''
    });

    const mapDispatchToProps = (dispatch) => ({
        startLogout: () => dispatch(startLogout()),
        startSetIdiom: (idiom) => dispatch(startSetIdiom(idiom)),
        startSetIdioms: () => dispatch(startSetIdioms())
    });

    export default connect(mapStateToProps, mapDispatchToProps)(NavComponent);

0 个答案:

没有答案