ReactJS - উপাদানটিতে কাস্টম ইভেন্ট শ্রোতাদের যুক্ত করুন


89

সাধারণ পুরানো জাভাস্ক্রিপ্টে আমার ডিআইভি আছে

<div class="movie" id="my_movie">

এবং নিম্নলিখিত জাভাস্ক্রিপ্ট কোড

var myMovie = document.getElementById('my_movie');
myMovie.addEventListener('nv-enter', function (event) {
     console.log('change scope');
});

এখন আমার একটি প্রতিক্রিয়া উপাদান রয়েছে, এই উপাদানটির ভিতরে, রেন্ডার পদ্ধতিতে, আমি আমার ডিভিটি ফিরিয়ে দিচ্ছি। আমি কীভাবে আমার কাস্টম ইভেন্টের জন্য ইভেন্ট শ্রোতা যুক্ত করতে পারি? (আমি এই লাইব্রেরিটি টিভি অ্যাপগুলির জন্য ব্যবহার করছি - নেভিগেশন )

import React, { Component } from 'react';

class MovieItem extends Component {

  render() {

    if(this.props.index === 0) {
      return (
        <div aria-nv-el aria-nv-el-current className="menu_item nv-default">
            <div className="indicator selected"></div>
            <div className="category">
                <span className="title">{this.props.movieItem.caption.toUpperCase()}</span>
            </div>
        </div>
      );
    }
    else {
      return (
        <div aria-nv-el className="menu_item nv-default">
            <div className="indicator selected"></div>
            <div className="category">
                <span className="title">{this.props.movieItem.caption.toUpperCase()}</span>
            </div>
        </div>
      );
    }
  }

}

export default MovieItem;

আপডেট # 1:

এখানে চিত্র বর্ণনা লিখুন

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

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class MenuItem extends Component {

  constructor(props) {
    super(props);
    // Pre-bind your event handler, or define it as a fat arrow in ES7/TS
    this.handleNVFocus = this.handleNVFocus.bind(this);
    this.handleNVEnter = this.handleNVEnter.bind(this);
    this.handleNVRight = this.handleNVRight.bind(this);
  }

  handleNVFocus = event => {
      console.log('Focused: ' + this.props.menuItem.caption.toUpperCase());
  }

  handleNVEnter = event => {
      console.log('Enter: ' + this.props.menuItem.caption.toUpperCase());
  }

  handleNVRight = event => {
      console.log('Right: ' + this.props.menuItem.caption.toUpperCase());
  }

  componentDidMount() {
    ReactDOM.findDOMNode(this).addEventListener('nv-focus', this.handleNVFocus);
    ReactDOM.findDOMNode(this).addEventListener('nv-enter', this.handleNVEnter);
    ReactDOM.findDOMNode(this).addEventListener('nv-right', this.handleNVEnter);
    //this.refs.nv.addEventListener('nv-focus', this.handleNVFocus);
    //this.refs.nv.addEventListener('nv-enter', this.handleNVEnter);
    //this.refs.nv.addEventListener('nv-right', this.handleNVEnter);
  }

  componentWillUnmount() {
    ReactDOM.findDOMNode(this).removeEventListener('nv-focus', this.handleNVFocus);
    ReactDOM.findDOMNode(this).removeEventListener('nv-enter', this.handleNVEnter);
    ReactDOM.findDOMNode(this).removeEventListener('nv-right', this.handleNVRight);
    //this.refs.nv.removeEventListener('nv-focus', this.handleNVFocus);
    //this.refs.nv.removeEventListener('nv-enter', this.handleNVEnter);
    //this.refs.nv.removeEventListener('nv-right', this.handleNVEnter);
  }

  render() {
    var attrs = this.props.index === 0 ? {"aria-nv-el-current": true} : {};
    return (
      <div ref="nv" aria-nv-el {...attrs} className="menu_item nv-default">
          <div className="indicator selected"></div>
          <div className="category">
              <span className="title">{this.props.menuItem.caption.toUpperCase()}</span>
          </div>
      </div>
    )
  }

}

export default MenuItem;

আমি কিছু লাইন মন্তব্য করে রেখেছি কারণ উভয় ক্ষেত্রেই আমি কনসোল লাইনগুলি লগ করতে সক্ষম হই না।

আপডেট # 2: এই নেভিগেশন লাইব্রেরিটি এর মূল এইচটিএমএল ট্যাগগুলির সাথে প্রতিক্রিয়া নিয়ে ভাল কাজ করে না, সুতরাং আমার বিকল্পগুলি সেট করতে হয়েছিল এবং আরিয়া- * ব্যবহার করার জন্য ট্যাগগুলির নাম পরিবর্তন করতে হয়েছিল যাতে এটি প্রতিক্রিয়াটির কোনও প্রভাব ফেলবে না।

navigation.setOption('prefix','aria-nv-el');
navigation.setOption('attrScope','aria-nv-scope');
navigation.setOption('attrScopeFOV','aria-nv-scope-fov');
navigation.setOption('attrScopeCurrent','aria-nv-scope-current');
navigation.setOption('attrElement','aria-nv-el');
navigation.setOption('attrElementFOV','aria-nv-el-fov');
navigation.setOption('attrElementCurrent','aria-nv-el-current');

@ আমি মূলত এই ফাইলটি থেকে উদাহরণটি ব্যবহার করছি ( github.com/ahiipsa/navication/blob/master/demo/index.html )
থিয়াগো

আপনার কন্সট্রাক্টর ( this.handleNVEnter = this.handleNVEnter.bind(this)) এ উভয়ই প্রি- বন্ডিং করার প্রয়োজন নেই এবং তীর ফাংশন ( handleNVEnter = enter => {}) সহ ES7 সম্পত্তি ইনিশিয়েলাইজার ব্যবহার করুন কারণ ফ্যাট অ্যার ফাংশন সর্বদা আবদ্ধ থাকে। আপনি যদি ES7 সিনট্যাক্স ব্যবহার করতে পারেন তবে এটির সাথে যান।
অ্যারন বেল

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

আমি পরিবর্তন সুপারিশ করবে aria-*করার data-*কারণ Gmail- কে বৈশিষ্ট্যাবলী একটি প্রমিত সেট থেকে এসেছ, আপনি আপনার নিজের আপ করতে পারবেন না। ডেটা অ্যাট্রিবিউটগুলি আপনি যা চান তার চেয়ে বেশি নির্বিচারে সেট করা যেতে পারে।
মারসি

উত্তর:


87

আপনার যদি ইতিমধ্যে প্রতিক্রিয়া দ্বারা সরবরাহ না করা DOM ইভেন্টগুলি পরিচালনা করতে হয় তবে উপাদানটি মাউন্ট হওয়ার পরে আপনাকে DOM শ্রোতাদের যুক্ত করতে হবে:

আপডেট: 13, 14 এবং 15 এর মধ্যে প্রতিক্রিয়াগুলির মধ্যে আমার উত্তরকে প্রভাবিত করে এমন এপিআইতে 15 টি পরিবর্তন করা হয়েছিল। প্রতিক্রিয়া 15 এবং ES7 ব্যবহারের নীচে সর্বশেষতম উপায় is পুরানো সংস্করণগুলির উত্তর ইতিহাস দেখুন ।

class MovieItem extends React.Component {

  componentDidMount() {
    // When the component is mounted, add your DOM listener to the "nv" elem.
    // (The "nv" elem is assigned in the render function.)
    this.nv.addEventListener("nv-enter", this.handleNvEnter);
  }

  componentWillUnmount() {
    // Make sure to remove the DOM listener when the component is unmounted.
    this.nv.removeEventListener("nv-enter", this.handleNvEnter);
  }

  // Use a class arrow function (ES7) for the handler. In ES6 you could bind()
  // a handler in the constructor.
  handleNvEnter = (event) => {
    console.log("Nv Enter:", event);
  }

  render() {
    // Here we render a single <div> and toggle the "aria-nv-el-current" attribute
    // using the attribute spread operator. This way only a single <div>
    // is ever mounted and we don't have to worry about adding/removing
    // a DOM listener every time the current index changes. The attrs 
    // are "spread" onto the <div> in the render function: {...attrs}
    const attrs = this.props.index === 0 ? {"aria-nv-el-current": true} : {};

    // Finally, render the div using a "ref" callback which assigns the mounted 
    // elem to a class property "nv" used to add the DOM listener to.
    return (
      <div ref={elem => this.nv = elem} aria-nv-el {...attrs} className="menu_item nv-default">
        ...
      </div>
    );
  }

}

কোডেপেন.ওয়ের উপর উদাহরণ


4
আপনি অপব্যবহার করছেন findDOMNode। আপনার ক্ষেত্রে var elem = this.refs.nv;যথেষ্ট।
পাভলো

4
@ পাভলো এইচএম, আপনি ঠিক বলেছেন, দেখে মনে হচ্ছে এটি v.14-এ পরিবর্তিত হয়েছে (v.13 এর মতো প্রতিক্রিয়া উপাদানটির পরিবর্তে DOM উপাদানটি ফিরিয়ে দিতে, যা আমি ব্যবহার করছি)। ধন্যবাদ
অ্যারন বেল

4
আমাকে কেন উপাদানটি আনমাউন্ট করা অবস্থায় DOM শ্রোতার অপসারণের বিষয়টি নিশ্চিত করতে হবে? এমন কোনও উত্স আছে যে তারা ফাঁস তৈরি করবে?
Fen1kz

4
@levininja edited Aug 19 at 6:19পোস্টের নীচে পাঠ্যটি ক্লিক করুন , যা আপনাকে ইতিহাস পুনর্বিবেচনায় নিয়ে যায়
অ্যারন বেল

4
@ নিকোলাসএস.এক্সু প্রতিক্রিয়া কোনও কাস্টম ইভেন্ট প্রেরণকারী এপিআই সরবরাহ করে না কারণ আপনি কলব্যাক প্রপস ব্যবহার করবেন বলে আশা করা হচ্ছে ( এই উত্তরটি দেখুন ), তবে nv.dispatchEvent()আপনার প্রয়োজন হলে আপনি স্ট্যান্ডার্ড ডিওএম ব্যবহার করতে পারেন ।
অ্যারন বেল

20

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

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class MovieItem extends Component
{
    _handleNVEvent = event => {
        ...
    };

    componentDidMount() {
        ReactDOM.findDOMNode(this).addEventListener('nv-event', this._handleNVEvent);
    }

    componentWillUnmount() {
        ReactDOM.findDOMNode(this).removeEventListener('nv-event', this._handleNVEvent);
    }

    [...]

}

export default MovieItem;

হাই @vbarbarosh, আমি আরও বিশদ সহ প্রশ্নটি আপডেট করেছি
থিয়াগো

4

প্রথমে, কাস্টম ইভেন্টগুলি দেশীয়ভাবে প্রতিক্রিয়া উপাদানগুলির সাথে ভাল খেলেন না। সুতরাং আপনি <div onMyCustomEvent={something}>রেন্ডার ফাংশনটিতে কেবল বলতে পারবেন না, এবং সমস্যাটি সম্পর্কে ভাবতে হবে।

দ্বিতীয়ত, আপনি যে লাইব্রেরিটি ব্যবহার করছেন তার ডকুমেন্টেশনটি একবার দেখার পরে, ইভেন্টটি আসলে চালিত হয় document.body, সুতরাং এটি যদি কাজ না করে, আপনার ইভেন্ট হ্যান্ডলারটি কখনই ট্রিগার করতে পারে না।

পরিবর্তে, componentDidMountআপনার আবেদনের কোথাও ভিতরে , আপনি যোগ করে এনভি-এন্টার শুনতে পারেন

document.body.addEventListener('nv-enter', function (event) {
    // logic
});

তারপরে, কলব্যাক ফাংশনের অভ্যন্তরে এমন কোনও ফাংশন হিট করুন যা উপাদানটির অবস্থা বা আপনি যা করতে চান তা পরিবর্তন করে।


4
"কাস্টম ইভেন্টগুলি দেশীয়ভাবে প্রতিক্রিয়াশীল উপাদানগুলির সাথে ভাল খেলেন না" এর কারণটি ব্যাখ্যা করতে আপনি সাহায্য করতে পারেন?
কোডফুল.এলেটমেন্ট

4
@ কোডফুল.এলিমেন্ট, এই সাইটে এই সম্পর্কে কিছু তথ্য রয়েছে: কাস্টম
-
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.