কীভাবে কোনও প্রতিক্রিয়া / রেডাক্স / টাইপস্ক্রিপ্ট বিজ্ঞপ্তি বার্তায় কোনও উপাদানকে আনমাউন্ট, আনেন্ডার করতে বা অপসারণ করতে হয়


114

আমি জানি এই প্রশ্নটি ইতিমধ্যে দু'বার জিজ্ঞাসা করা হয়েছে তবে বেশিরভাগ সময় সমাধানটি হ'ল পিতামাতার মধ্যে এটি পরিচালনা করা, কারণ দায়বদ্ধতার প্রবাহ কেবল অবনমিত হয়। যাইহোক, কখনও কখনও, আপনাকে এর একটি পদ্ধতি থেকে কোনও উপাদানকে হত্যা করতে হবে। আমি জানি আমি এর প্রপসগুলি সংশোধন করতে পারছি না, এবং আমি যদি রাজ্য হিসাবে বুলিয়ান যোগ করতে শুরু করি তবে এটি একটি সাধারণ উপাদানটির জন্য সত্যিই অগোছালো হতে শুরু করবে। আমি যা অর্জন করতে চাইছি তা এখানে: একটি ক্ষুদ্র ত্রুটি বাক্স উপাদান যা তাকে খারিজ করার জন্য একটি "এক্স" রয়েছে। এর প্রপসের মাধ্যমে ত্রুটি পাওয়া এটি প্রদর্শিত হবে তবে আমি এটির নিজের কোড থেকে এটি বন্ধ করার উপায় চাই।

class ErrorBoxComponent extends React.Component {

  dismiss() {
    // What should I put here?
  }
  
  render() {
    if (!this.props.error) {
      return null;
    }

    return (
      <div data-alert className="alert-box error-box">
        {this.props.error}
        <a href="#" className="close" onClick={this.dismiss.bind(this)}>&times;</a>
      </div>
    );
  }
}


export default ErrorBoxComponent;

এবং আমি এটি প্যারেন্ট উপাদানগুলিতে এটি ব্যবহার করব:

<ErrorBox error={this.state.error}/>

বিভাগে আমার এখানে কী রাখা উচিত? , আমি ইতিমধ্যে চেষ্টা করেছি:

ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(this).parentNode); যা কনসোলে একটি দুর্দান্ত ত্রুটি ছুঁড়েছে:

সতর্কতা: আনমাউন্টকম্পোনট্যান্ট অ্যাটনোড (): আপনি যে নোডটি আনমাউন্ট করতে চাইছেন তা রিঅ্যাক্ট দ্বারা রেন্ডার হয়েছিল এবং এটি কোনও শীর্ষ-স্তরের ধারক নয়। পরিবর্তে, এই উপাদানটি সরানোর জন্য প্যারেন্ট উপাদানটিকে তার স্থিতি আপডেট করতে হবে এবং পুনরায় সরবরাহ করতে হবে।

আমি কি ত্রুটিবক্সের রাজ্যে আগত প্রপসগুলি অনুলিপি করব এবং কেবলমাত্র এটি অভ্যন্তরীণভাবে চালিত করব?


আপনি কি রেডাক্স ব্যবহার করছেন?
আর্নউ লাকামব্রা

এটি প্রয়োজনীয়তা কেন "এর প্রপসের মাধ্যমে ত্রুটি পাওয়া এটি প্রদর্শিত হবে তবে আমি তার নিজস্ব কোড থেকে এটি বন্ধ করার উপায় চাই?" স্বাভাবিক পদ্ধতিটি এমন কোনও ক্রিয়া প্রেরণ করা হবে যা ত্রুটিজনিত অবস্থা সাফ করবে এবং পিতা-মাতার রেন্ডার চক্রের মধ্যে আপনাকে যেমন নির্দেশিত হয়েছিল তেমন বন্ধ হয়ে যাবে।
ken4z

আমি আসলে উভয়ের পক্ষে সম্ভাবনাটি অফার করতে চাই। প্রকৃতপক্ষে, আপনি এটি ব্যাখ্যা করার সাথে সাথে এটি বন্ধ হয়ে যাবে, তবে আমার কেসটি "যদি আমি এটি ভিতরে থেকে বন্ধ করতে সক্ষম হতে চাই তবে কী হবে"
সেফি

উত্তর:


97

আপনি যে দুর্দান্ত সতর্কতা পেয়েছিলেন ঠিক তেমনই আপনি এমন কিছু করার চেষ্টা করছেন যা প্রতিক্রিয়াবিরোধী একটি প্যাটার্ন is এটি একটি নো প্রতিক্রিয়া অভিভাবকদের কাছ থেকে সন্তানের সম্পর্কের ক্ষেত্রে কোনও আনমাউন্ট ঘটানোর উদ্দেশ্য। এখন আপনি যদি কোনও শিশু নিজেই আনমাউন্ট করতে চান, তবে আপনি সন্তানের দ্বারা চালিত অভিভাবকের রাজ্যের পরিবর্তনের সাথে এটি অনুকরণ করতে পারেন। আমাকে কোডে আপনাকে দেখাতে দিন

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}
    }

}

এটি একটি খুব সাধারণ উদাহরণ। তবে আপনি কোনও ক্রিয়াকলাপ পিতামাতার কাছে যাওয়ার কোনও উপায় দেখতে পারেন

এটি বলা হচ্ছে যে আপনার স্টোরটি যখন রেন্ডার হয় তখন আপনার স্টোরটিকে সঠিক তথ্য রাখার অনুমতি দেওয়ার জন্য আপনার সম্ভবত স্টোরের (প্রেরণ ক্রিয়া) কাজ করা উচিত

দুটি পৃথক অ্যাপ্লিকেশনের জন্য আমি ত্রুটি / স্থিতির বার্তা করেছি, উভয়ই স্টোর দিয়ে গিয়েছিলাম। এটি পছন্দসই পদ্ধতি ... আপনি চাইলে আমি কীভাবে এটি করতে পারি তার জন্য কিছু কোড পোস্ট করতে পারি।

সম্পাদনা: এখানে আমি কীভাবে প্রতিক্রিয়া / রেডাক্স / টাইপস্ক্রিপ্ট ব্যবহার করে একটি বিজ্ঞপ্তি সিস্টেম সেট আপ করব

প্রথমে কিছু বিষয় লক্ষণীয়। এটি টাইপস্ক্রিপ্টে তাই আপনার প্রকারের ঘোষণাগুলি সরিয়ে ফেলতে হবে :)

আমি অপারেশনের জন্য এনপিএম প্যাকেজ লোড্যাশ এবং ইনলাইন ক্লাসনেম অ্যাসাইনমেন্টের জন্য ক্লাসের নামগুলি (সিএক্স ওরফে) ব্যবহার করছি।

এই সেটআপটির সৌন্দর্য হ'ল আমি ক্রিয়াকলাপটি তৈরি করার সময় প্রতিটি বিজ্ঞপ্তির জন্য একটি অনন্য শনাক্তকারী ব্যবহার করি। (যেমন 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>
        );
    }
}

1
"স্টোর দিয়ে"? আমি মনে করি, আমি সে সম্পর্কে কয়েকটি গুরুত্বপূর্ণ পাঠাচ্ছি না: উত্তর এবং কোডটির জন্য ধন্যবাদ তবে আপনি কি মনে করেন না যে এটি একটি সাধারণ ত্রুটি বার্তা প্রদর্শন উপাদানটির জন্য গুরুতরভাবে ওভারকিল করছে? সন্তানের উপর সংজ্ঞায়িত কোনও ক্রিয়া পরিচালনা করা পিতামাতার দায়িত্ব হওয়া উচিত নয় ...
সেফি

এটি পিতামাতাকে প্রকৃতপক্ষে হওয়া উচিত যেহেতু পিতা-মাতার দায়িত্ব শিশুকে প্রথমে ডিওমে রাখার জন্য দায়বদ্ধ। আমি যদিও বলছিলাম, যদিও এটি করার এটি একটি উপায় তবে আমি এটির সুপারিশ করব না। আপনার স্টোর আপডেট হওয়া একটি ক্রিয়া ব্যবহার করা উচিত। ফ্লাক্স এবং রেডাক্স উভয়ই ধরণগুলি এভাবে ব্যবহার করা উচিত।
জন রুডেল

ঠিক আছে, আইডি আপনি যদি দয়া করে কোড টুকরা কিছু পয়েন্টার পেয়ে খুশি। আমি ফ্লাক্স এবং রেডুক উভয়ের সম্পর্কে যখন কিছুটা পড়েছি তখন আমি সেই কোডের টুকরোটি ফিরে পাব!
সেফি

ঠিক আছে হ্যাঁ আমি মনে করি আমি এটি করার একটি উপায় দেখিয়ে একটি সাধারণ গিথুব রেপো তৈরি করব। আমি সর্বশেষে আমি সিএসএস অ্যানিমেশনগুলি ফিড আউট করে ফেলার জন্য ব্যবহার করলাম যা স্ট্রিং বা এইচটিএমএল উপাদানগুলি রেন্ডার করতে পারে এবং তারপরে অ্যানিমেশনটি শেষ হয়ে গেলে আমি জাভাস্ক্রিপ্ট ব্যবহার করে তার জন্য শোনার জন্য এবং তারপরে নিজেকে পরিষ্কার করে ফেলতাম (ডিওএম থেকে সরান) যখন অ্যানিমেশন শেষ হয়েছে বা আপনি বরখাস্ত বোতামটি ক্লিক করেছেন।
জন রুডেল

দয়া করে করুন, যদি এটি আমার মতো অন্যদের সহায়তা করতে পারে যারা প্রতিক্রিয়াটির দর্শন বুঝতে কিছুটা লড়াই করেন। এছাড়াও, আমি সময় নিয়ে আমার পয়েন্টগুলির সাথে কিছুটা ভাগ করে নিতে পেরে আনন্দিত যদি আপনি এটির জন্য গিট রেপো রাখেন! একশ পয়েন্ট বলতে দিন (যদিও 2 দিনের মধ্যে অনুদান পাওয়া যায়)
সেফি

25

পরিবর্তে ব্যবহার

ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(this).parentNode);

ব্যবহার করার চেষ্টা করুন

ReactDOM.unmountComponentAtNode(document.getElementById('root'));

15 কেউ প্রতিক্রিয়া দিয়ে এটি চেষ্টা করেছে? এটি উভয়ই সম্ভাব্য-দরকারী এবং সম্ভবত একটি অ্যান্টি-প্যাটার্ন বলে মনে হচ্ছে।
দ্য উথারসাইড

4
@ থাইউটারসাইড এটি প্রতিক্রিয়া হিসাবে একটি বিরোধী নিদর্শন। প্রতিক্রিয়া দস্তাবেজগুলি আপনাকে রাষ্ট্র /
প্রপসের

1
যদি উপাদানটি আনমাউন্ট করা না হয় তবে আপনার প্রতিক্রিয়া অ্যাপ্লিকেশনটির মূল হলেও মূল উপাদানটি প্রতিস্থাপন করা হচ্ছে না? উদাহরণস্বরূপ <div id="c1"><div id="c2"><div id="react-root" /></div></div>। অভ্যন্তরের পাঠ্যটি c1প্রতিস্থাপন হয়ে গেলে কী হবে ?
ফ্লিপডব্বট

1
আপনি যদি আপনার মূল উপাদানটিকে আনমাউন্ট করতে চান তবে এটি কার্যকর especially বিশেষত আপনার যদি অ-প্রতিক্রিয়া অ্যাপ্লিকেশনটিতে কোনও প্রতিক্রিয়াশীল অ্যাপ থাকে। আমাকে এটি ব্যবহার করতে হয়েছিল কারণ আমি অন্য অ্যাপ্লিকেশন দ্বারা পরিচালিত কোনও মডেলের অভ্যন্তরে প্রতিক্রিয়া জানাতে চেয়েছিলাম এবং তাদের মডেলের কাছে ঘনিষ্ঠ বোতাম রয়েছে যা মডেলটি আড়াল করে রাখবে তবে আমার র্যাক্টডোম এখনও মাউন্ট থাকবে না। reactjs.org/blog/2015/10/01/react-render-and-top-level-api.html
আব্বা

10

বেশিরভাগ ক্ষেত্রে, উপাদানটি লুকিয়ে রাখাই যথেষ্ট, উদাহরণস্বরূপ:

export default class ErrorBoxComponent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            isHidden: false
        }
    }

    dismiss() {
        this.setState({
            isHidden: true
        })
    }

    render() {
        if (!this.props.error) {
            return null;
        }

        return (
            <div data-alert className={ "alert-box error-box " + (this.state.isHidden ? 'DISPLAY-NONE-CLASS' : '') }>
                { this.props.error }
                <a href="#" className="close" onClick={ this.dismiss.bind(this) }>&times;</a>
            </div>
        );
    }
}

অথবা আপনি প্যারেন্ট উপাদানগুলির মাধ্যমে এই জাতীয়ভাবে রেন্ডার / রেন্ডার / রেন্ডার করতে পারেন না

export default class ParentComponent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            isErrorShown: true
        }
    }

    dismiss() {
        this.setState({
            isErrorShown: false
        })
    }

    showError() {
        if (this.state.isErrorShown) {
            return <ErrorBox 
                error={ this.state.error }
                dismiss={ this.dismiss.bind(this) }
            />
        }

        return null;
    }

    render() {

        return (
            <div>
                { this.showError() }
            </div>
        );
    }
}

export default class ErrorBoxComponent extends React.Component {
    dismiss() {
        this.props.dismiss();
    }

    render() {
        if (!this.props.error) {
            return null;
        }

        return (
            <div data-alert className="alert-box error-box">
                { this.props.error }
                <a href="#" className="close" onClick={ this.dismiss.bind(this) }>&times;</a>
            </div>
        );
    }
}

শেষ অবধি, এইচটিএমএল নোড অপসারণ করার একটি উপায় আছে তবে আমি সত্যিই জানি না এটি একটি ভাল ধারণা। অভ্যন্তরীণ থেকে প্রতিক্রিয়া জানেন এমন কেউ হয়ত এ সম্পর্কে কিছু বলবেন।

export default class ErrorBoxComponent extends React.Component {
    dismiss() {
        this.el.remove();
    }

    render() {
        if (!this.props.error) {
            return null;
        }

        return (
            <div data-alert className="alert-box error-box" ref={ (el) => { this.el = el} }>
                { this.props.error }
                <a href="#" className="close" onClick={ this.dismiss.bind(this) }>&times;</a>
            </div>
        );
    }
}

তবে, সেই ক্ষেত্রে যে আমি শিশুদের তালিকার ভিতরে থাকা কোনও শিশুকে আনমাউন্ট করতে চাই ... আমি যদি সেই তালিকার একই কী দিয়ে একটি ক্লোনযুক্ত উপাদান প্রতিস্থাপন করতে চাই তবে আমি কী করতে পারি?
রোডেভ

1
যেহেতু আমি বুঝতে পেরেছি আপনি এর মতো কিছু করতে চান: ডকুমেন্ট.সেটমেন্টমেন্টবাইআইডি (CHILD_NODE_ID) ->। সরান (); -> ডকুমেন্ট.সেটমেন্ট বিইআইডি (PARENT_NODE_ID) -> .এপেন্ডচিল্ড (NEW_NODE)? আমি কি সঠিক? এটি ভুলে যাও এটি পদ্ধতির প্রতিক্রিয়া নয়। শর্ত রেন্ডারিংয়ের জন্য উপাদান রাষ্ট্রটি ব্যবহার করুন
সাশা কোস

2

আমি এখন প্রায় 10 বার এই পোস্টে এসেছি এবং আমি আমার দুটি সেন্ট এখানে রেখে যেতে চাই। আপনি কেবল এটি শর্তসাপেক্ষে আনমাউন্ট করতে পারেন।

if (renderMyComponent) {
  <MyComponent props={...} />
}

এটি আনমাউন্ট করার জন্য আপনাকে যা করতে হবে তা হ'ল ডিওএম থেকে এটি সরিয়ে ফেলতে হবে।

যতক্ষণ না renderMyComponent = true, উপাদানটি রেন্ডার হবে। আপনি যদি সেট করেন renderMyComponent = false, এটি ডিওএম থেকে আনমাউন্ট করবে।


-1

এটি সমস্ত পরিস্থিতিতে উপযুক্ত return falseনয় তবে নির্দিষ্ট শর্তটি মেটানো বা পূরণ না হলে আপনি শর্তসাপেক্ষে উপাদানটির অভ্যন্তরেই থাকতে পারেন।

এটি উপাদানটি আনমাউন্ট করে না, তবে এটি সমস্ত রেন্ডার করা সামগ্রী সরিয়ে দেয়। এটি কেবল খারাপ হবে, মনে মনে, যদি উপাদানটিতে ইভেন্ট শ্রোতাদের উপস্থিত থাকে যা উপাদানটির আর প্রয়োজন নেই তখন অপসারণ করা উচিত।

import React, { Component } from 'react';

export default class MyComponent extends Component {
    constructor(props) {
        super(props);

        this.state = {
            hideComponent: false
        }
    }

    closeThis = () => {
        this.setState(prevState => ({
            hideComponent: !prevState.hideComponent
        })
    });

    render() {
        if (this.state.hideComponent === true) {return false;}

        return (
            <div className={`content`} onClick={() => this.closeThis}>
                YOUR CODE HERE
            </div>
        );
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.