Как и в том приятном предупреждении, которое вы получили, вы пытаетесь сделать что-то, что является антипаттерном в React. Это нет-нет. React предназначен для размонтирования родительских и дочерних отношений. Теперь, если вы хотите, чтобы дочерний элемент отключился, вы можете смоделировать это с помощью изменения состояния в родительском элементе, которое запускается дочерним элементом. позвольте мне показать вам код.
class Child extends React.Component {
constructor(){}
dismiss() {
this.props.unmountMe();
}
render(){
// code
}
}
class Parent ...
constructor(){
super(props)
this.state = {renderChild: true};
this.handleChildUnmount = this.handleChildUnmount.bind(this);
}
handleChildUnmount(){
this.setState({renderChild: false});
}
render(){
// code
{this.state.renderChild ? <Child unmountMe={this.handleChildUnmount} /> : null}
}
}
это очень простой пример. но вы можете увидеть грубый способ передать родителю действие
При этом вам, вероятно, следует пройти через магазин (действие отправки), чтобы ваш магазин содержал правильные данные, когда он идет на рендеринг.
Я делал сообщения об ошибках / статусе для двух отдельных приложений, оба прошли через магазин. Это предпочтительный метод ... Если хотите, я могу опубликовать код, как это сделать.
РЕДАКТИРОВАТЬ: вот как я настроил систему уведомлений с помощью React / Redux / Typescript
Прежде всего, следует отметить несколько моментов. это в машинописном тексте, поэтому вам нужно удалить объявления типов :)
Я использую lodash пакетов npm для операций и имена классов (псевдоним cx) для встроенного назначения имен классов.
Прелесть этой настройки в том, что я использую уникальный идентификатор для каждого уведомления, когда действие его создает. (например, notify_id). Этот уникальный идентификатор - это Symbol()
. Таким образом, если вы хотите удалить любое уведомление в любой момент времени, вы можете это сделать, потому что вы знаете, какое из них нужно удалить. Эта система уведомлений позволит вам складывать столько, сколько вы хотите, и они исчезнут, когда анимация будет завершена. Я подключаюсь к событию анимации, и когда оно завершается, я запускаю код для удаления уведомления. Я также установил запасной тайм-аут, чтобы удалить уведомление на случай, если обратный вызов анимации не сработает.
уведомление-действия.ts
import { USER_SYSTEM_NOTIFICATION } from '../constants/action-types';
interface IDispatchType {
type: string;
payload?: any;
remove?: Symbol;
}
export const notifySuccess = (message: any, duration?: number) => {
return (dispatch: Function) => {
dispatch({ type: USER_SYSTEM_NOTIFICATION, payload: { isSuccess: true, message, notify_id: Symbol(), duration } } as IDispatchType);
};
};
export const notifyFailure = (message: any, duration?: number) => {
return (dispatch: Function) => {
dispatch({ type: USER_SYSTEM_NOTIFICATION, payload: { isSuccess: false, message, notify_id: Symbol(), duration } } as IDispatchType);
};
};
export const clearNotification = (notifyId: Symbol) => {
return (dispatch: Function) => {
dispatch({ type: USER_SYSTEM_NOTIFICATION, remove: notifyId } as IDispatchType);
};
};
уведомление-reducer.ts
const defaultState = {
userNotifications: []
};
export default (state: ISystemNotificationReducer = defaultState, action: IDispatchType) => {
switch (action.type) {
case USER_SYSTEM_NOTIFICATION:
const list: ISystemNotification[] = _.clone(state.userNotifications) || [];
if (_.has(action, 'remove')) {
const key = parseInt(_.findKey(list, (n: ISystemNotification) => n.notify_id === action.remove));
if (key) {
// mutate list and remove the specified item
list.splice(key, 1);
}
} else {
list.push(action.payload);
}
return _.assign({}, state, { userNotifications: list });
}
return state;
};
app.tsx
в базовом рендере для вашего приложения вы будете рендерить уведомления
render() {
const { systemNotifications } = this.props;
return (
<div>
<AppHeader />
<div className="user-notify-wrap">
{ _.get(systemNotifications, 'userNotifications') && Boolean(_.get(systemNotifications, 'userNotifications.length'))
? _.reverse(_.map(_.get(systemNotifications, 'userNotifications', []), (n, i) => <UserNotification key={i} data={n} clearNotification={this.props.actions.clearNotification} />))
: null
}
</div>
<div className="content">
{this.props.children}
</div>
</div>
);
}
user-notification.tsx
класс уведомления пользователя
/*
Simple notification class.
Usage:
<SomeComponent notifySuccess={this.props.notifySuccess} notifyFailure={this.props.notifyFailure} />
these two functions are actions and should be props when the component is connect()ed
call it with either a string or components. optional param of how long to display it (defaults to 5 seconds)
this.props.notifySuccess('it Works!!!', 2);
this.props.notifySuccess(<SomeComponentHere />, 15);
this.props.notifyFailure(<div>You dun goofed</div>);
*/
interface IUserNotifyProps {
data: any;
clearNotification(notifyID: symbol): any;
}
export default class UserNotify extends React.Component<IUserNotifyProps, {}> {
public notifyRef = null;
private timeout = null;
componentDidMount() {
const duration: number = _.get(this.props, 'data.duration', '');
this.notifyRef.style.animationDuration = duration ? `${duration}s` : '5s';
// fallback incase the animation event doesn't fire
const timeoutDuration = (duration * 1000) + 500;
this.timeout = setTimeout(() => {
this.notifyRef.classList.add('hidden');
this.props.clearNotification(_.get(this.props, 'data.notify_id') as symbol);
}, timeoutDuration);
TransitionEvents.addEndEventListener(
this.notifyRef,
this.onAmimationComplete
);
}
componentWillUnmount() {
clearTimeout(this.timeout);
TransitionEvents.removeEndEventListener(
this.notifyRef,
this.onAmimationComplete
);
}
onAmimationComplete = (e) => {
if (_.get(e, 'animationName') === 'fadeInAndOut') {
this.props.clearNotification(_.get(this.props, 'data.notify_id') as symbol);
}
}
handleCloseClick = (e) => {
e.preventDefault();
this.props.clearNotification(_.get(this.props, 'data.notify_id') as symbol);
}
assignNotifyRef = target => this.notifyRef = target;
render() {
const {data, clearNotification} = this.props;
return (
<div ref={this.assignNotifyRef} className={cx('user-notification fade-in-out', {success: data.isSuccess, failure: !data.isSuccess})}>
{!_.isString(data.message) ? data.message : <h3>{data.message}</h3>}
<div className="close-message" onClick={this.handleCloseClick}>+</div>
</div>
);
}
}