Ответ 1
Просто как это хорошее предупреждение, которое вы получили, вы пытаетесь сделать что-то, что является Anti-Pattern in 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}
}
}
Это очень простой пример. но вы можете увидеть грубый способ передать родителю действие
При этом вам, вероятно, следует пройти через магазин (диспетчерское действие), чтобы ваш магазин мог содержать правильные данные, когда он идет для рендеринга
Я сделал сообщения об ошибке/статусе для двух отдельных приложений, оба прошли через хранилище. Его предпочтительный метод... Если вы хотите, я могу опубликовать некоторый код о том, как это сделать.
EDIT: Вот как я настраиваю систему уведомлений с использованием React/Redux/Typescript
Несколько вещей, которые нужно отметить первым.. это находится в typescript, поэтому вам нужно будет удалить объявления типа:)
Я использую пакеты lpm для npm для операций и classnames (cx alias) для присвоения имени inline classname.
Красота этой установки заключается в том, что я использую уникальный идентификатор для каждого уведомления, когда действие создает его. (например, notify_id). Этот уникальный идентификатор - Symbol()
. Таким образом, если вы хотите удалить любое уведомление в любой момент времени, вы можете, потому что знаете, какой из них удалить. Эта система уведомлений позволит вам складывать столько, сколько вы захотите, и они исчезнут, когда анимация будет завершена. Я подключаюсь к событию анимации, и когда он заканчивается, я запускаю код для удаления уведомления. Я также устанавливаю резервный тайм-аут, чтобы удалить уведомление, просто не получив обратного вызова анимации.
уведомление-actions.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>
);
}
пользователя 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>
);
}
}