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