Podobnie jak to miłe ostrzeżenie, które otrzymałeś, próbujesz zrobić coś, co jest anty-wzorcem w reakcji. To jest nie-nie. React ma na celu odłączenie od relacji rodzic-dziecko. Teraz, jeśli chcesz, aby dziecko się odmontowało, możesz to zasymulować za pomocą zmiany stanu w rodzicu, która jest wyzwalana przez dziecko. pokażę ci kod.
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}
}
}
to jest bardzo prosty przykład. ale możesz zobaczyć szorstki sposób przekazania rodzicowi działania
Biorąc to pod uwagę, prawdopodobnie powinieneś przechodzić przez sklep (akcja wysyłkowa), aby Twój sklep zawierał prawidłowe dane, gdy ma być renderowany
Zrobiłem komunikaty o błędach / stanie dla dwóch oddzielnych aplikacji, obie przeszły przez sklep. Jest to preferowana metoda ... Jeśli chcesz, mogę opublikować kod, jak to zrobić.
EDYCJA: Oto jak skonfigurowałem system powiadomień za pomocą React / Redux / Typescript
Kilka rzeczy na początek. to jest w maszynie, więc musisz usunąć deklaracje typu :)
Używam pakietów npm lodash do operacji i nazw klas (alias cx) do przypisania w wierszu nazwy klasy.
Piękno tej konfiguracji polega na tym, że używam unikalnego identyfikatora dla każdego powiadomienia, gdy akcja je tworzy. (np. notify_id). Ten unikalny identyfikator to Symbol()
. W ten sposób, jeśli chcesz usunąć jakiekolwiek powiadomienie w dowolnym momencie, możesz to zrobić, ponieważ wiesz, które z nich usunąć. Ten system powiadomień pozwoli Ci ułożyć tyle, ile chcesz, i znikną po zakończeniu animacji. Podłączam się do zdarzenia animacji i kiedy się kończy, uruchamiam kod, aby usunąć powiadomienie. Ustawiłem również rezerwowy limit czasu, aby usunąć powiadomienie na wypadek, gdyby wywołanie zwrotne animacji nie zostało uruchomione.
powiadomienia-działania.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);
};
};
powiadomienie-reduktor.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
w podstawowym renderowaniu dla twojej aplikacji wyrenderowałbyś powiadomienia
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
klasa powiadamiania użytkownika
/*
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>
);
}
}