Как избежать повторного рендеринга компонента после изменения состояния редукции? - PullRequest
0 голосов
/ 16 января 2019

У меня есть система всплывающих уведомлений, реализованная с реакцией и редукцией, каждый раз, когда я хочу отправить всплывающее сообщение с сообщением, я вызываю действие переизбытка, которое изменит состояние редуктора, и в зависимости от состояния редуктора я показываю снэк-бар это находится в компоненте router, оборачивающем дочерние компоненты router, это работает очень хорошо, но у меня есть проблема с пользовательским интерфейсом, потому что каждый раз, когда появляется это уведомление, он перерисовывает компонент navbar, который содержит изображение, и вы можете увидеть, как перерисовывается изображение когда придет уведомление.

Это странно для меня, потому что действие уведомления не меняет состояние панели навигации, которая содержит изображение, поэтому я считаю, что оно не должно перерисовываться, поскольку оно не меняет своего состояния. Может кто-нибудь дать мне совет, что делать?

Я использовал 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);

после этого отображается снэк-бар, но он перерисовывает компонент navbar, который не использует это состояние и не имеет никакого отношения к редуктору, который показывает, что снэк-бар производит то, что изображение в navbar перерисовывается и не чувствует себя вполне естественно для пользователя.

Действия для всплывающего окна следующие:

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, который подключается к онлайн-хранилищу и содержит аватар, который мигает каждый раз, когда я вызываю уведомление о действиях.

    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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...