Cũng giống như cảnh báo tuyệt vời mà bạn nhận được, bạn đang cố gắng làm điều gì đó là Anti-Pattern trong React. Đây là điều không thể. React được thiết kế để không có mối quan hệ phụ huynh với con cái xảy ra một cách vô tận. Bây giờ nếu bạn muốn một đứa trẻ tự ngắt kết nối, bạn có thể mô phỏng điều này với sự thay đổi trạng thái ở cha mẹ do đứa trẻ kích hoạt. để tôi cho bạn xem mã.
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}
}
}
đây là một ví dụ rất đơn giản. nhưng bạn có thể thấy một cách đơn giản để chuyển cho cha mẹ một hành động
Điều đó đang được nói rằng bạn có thể nên duyệt qua cửa hàng (hành động điều phối) để cho phép cửa hàng của bạn chứa dữ liệu chính xác khi nó chuyển sang hiển thị
Tôi đã thực hiện thông báo lỗi / trạng thái cho hai ứng dụng riêng biệt, cả hai đều đã qua cửa hàng. Đó là phương pháp ưa thích ... Nếu bạn muốn, tôi có thể đăng một số mã về cách làm điều đó.
CHỈNH SỬA: Đây là cách tôi thiết lập hệ thống thông báo bằng React / Redux / Typescript
Một số điều cần lưu ý đầu tiên. cái này ở dạng typecript nên bạn sẽ cần xóa khai báo kiểu :)
Tôi đang sử dụng gói npm lodash cho các hoạt động và tên lớp (bí danh cx) để gán tên lớp nội tuyến.
Cái hay của thiết lập này là tôi sử dụng một số nhận dạng duy nhất cho mỗi thông báo khi hành động tạo ra nó. (ví dụ: Inform_id). ID duy nhất này là một Symbol()
. Bằng cách này nếu bạn muốn xóa bất kỳ thông báo nào bất kỳ lúc nào có thể vì bạn biết thông báo nào cần xóa. Hệ thống thông báo này sẽ cho phép bạn xếp chồng bao nhiêu tùy thích và chúng sẽ biến mất khi hoạt ảnh hoàn thành. Tôi đang kết nối sự kiện hoạt ảnh và khi nó kết thúc, tôi kích hoạt một số mã để xóa thông báo. Tôi cũng thiết lập thời gian chờ dự phòng để xóa thông báo trong trường hợp lệnh gọi lại hoạt ảnh không kích hoạt.
thông báo-hành động.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);
};
};
thông báo-giảm thiểu.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
trong kết xuất cơ sở cho ứng dụng của bạn, bạn sẽ hiển thị thông báo
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
lớp thông báo người dùng
/*
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>
);
}
}