[reactjs] 부모 노드와 통신하기위한 react.js 커스텀 이벤트

나는 CustomEvent부모 노드와 통신하기 위해 일반 DOM을 만들고 듣고 있습니다 .

어린이 :

  var moveEvent = new CustomEvent('the-graph-group-move', {
    detail: {
      nodes: this.props.nodes,
      x: deltaX,
      y: deltaY
    },
    bubbles: true
  });
  this.getDOMNode().dispatchEvent(moveEvent);

부모 :

componentDidMount: function () {
  this.getDOMNode().addEventListener("the-graph-group-move", this.moveGroup);
},

이것은 작동하지만 더 나은 React 전용 방법이 있습니까?



답변

위에서 언급 한대로 :

React 방식은 props를 통해 명시 적으로 자식에게 콜백을 전달하는 것입니다. React에서 버블 링이있는 사용자 지정 이벤트는 지원되지 않습니다.

반응 형 프로그래밍 추상화는 직교합니다.

관찰자 패턴을 사용하여 대화 형 시스템을 프로그래밍하는 것은 어렵고 오류가 발생하기 쉽지만 여전히 많은 프로덕션 환경에서 구현 표준입니다. 우리는 반응 형 프로그래밍 추상화를 위해 관찰자를 점차적으로 비난하는 접근 방식을 제시합니다. 여러 라이브러리 레이어는 프로그래머가 기존 코드를 콜백에서보다 선언적인 프로그래밍 모델로 원활하게 마이그레이션하는 데 도움이됩니다.

React 철학은 대신 명령 패턴을 기반으로합니다.

여기에 이미지 설명 입력

참고 문헌


답변

간단한 서비스를 작성하고 사용할 수 있습니다.

/** eventsService */
module.exports = {
  callbacks: {},

  /**
   * @param {string} eventName
   * @param {*} data
   */
  triggerEvent(eventName, data = null) {
    if (this.callbacks[eventName]) {
      Object.keys(this.callbacks[eventName]).forEach((id) => {
        this.callbacks[eventName][id](data);
      });
    }
  },

  /**
   * @param {string} eventName name of event
   * @param {string} id callback identifier
   * @param {Function} callback
   */
  listenEvent(eventName, id, callback) {
    this.callbacks[eventName][id] = callback;
  },

  /**
   * @param {string} eventName name of event
   * @param {string} id callback identifier
   */
  unlistenEvent(eventName, id) {
    delete this.callbacks[eventName][id];
  },
};

예 (트리거링과 동일)

import eventsService from '../../../../services/events';
export default class FooterMenu extends Component {
  componentWillMount() {
    eventsService
      .listenEvent('cart', 'footer', this.cartUpdatedListener.bind(this));
  }

  componentWillUnmount() {
    eventsService
      .unlistenEvent('cart', 'footer');
  }

  cartUpdatedListener() {
    console.log('cart updated');
  }
}


답변

컨텍스트를 통해 전달 된 콜백을 통해 이벤트를 버블 링 할 수 있습니다. [CodePen]

import * as React from 'react';

const MyEventContext = React.createContext(() => {});

const MyEventBubbleContext = ({children, onMyEvent}) => {
  const bubbleEvent = React.useContext(MyEventContext);
  const handleMyEvent = React.useCallback((...args) => {
    // stop propagation if handler returns false
    if (onMyEvent(...args) !== false) {
      // bubble the event
      bubbleEvent(...args);
    }
  }, [onMyEvent]);
  return (
    <MyEventContext.Provider value={handleMyEvent}>
      {children}
    </MyEventContext.Provider>
  );
};

const MyComponent = () => (
  <MyEventBubbleContext onMyEvent={e => console.log('grandparent got event: ', e)}>
    <MyEventBubbleContext onMyEvent={e => console.log('parent got event: ', e)}>
      <MyEventContext.Consumer>
        {onMyEvent => <button onClick={onMyEvent}>Click me</button>}
      </MyEventContext.Consumer>
    </MyEventBubbleContext>
  </MyEventBubbleContext>
);

export default MyComponent;


답변

특히 부모에서 자식으로 구멍을 뚫는 것이 이미 번거 롭다면 매우 합리적이라고 생각한 또 다른 것이 있습니다. 그는 그것을 덜 단순한 의사 소통이라고 불렀습니다. 링크는 다음과 같습니다.

https://github.com/ryanflorence/react-training/blob/gh-pages/lessons/04-less-simple-communication.md


답변

가능한 해결책 은 ReactJs 앱에서 Observer 패턴에 절대적으로 의존 해야하는 경우 일반 이벤트를 가로 챌 수 있습니다. 예를 들어, <div>삭제 <div>로 표시된를 삭제 키로 인해 발생 시키려면 customEvent에 의해 호출되는 keydown 이벤트를 수신하도록 할 수 있습니다 . 본문에 keydown을 트랩하고 customEvent선택한에 keydown 이벤트를 전달합니다 <div>. 누군가에게 도움이되는 경우 공유합니다.


답변

클라이언트에 상태를 배포 한 후 저장소에 ‘파견’상태를 백업하는 중앙 저장소 [Redux]도 관찰자 패턴과 같습니다. 게시 / 구독을 수행하는 방법은 props / events 경로를 연결하는 명시적인 (취약한?) 오버 헤드로 인해 더 나빠질뿐입니다. 계층 구조를 해킹하기 위해 React는 악취가 나는 컨텍스트 (제공자 패턴) 또는 관찰 가능한 라이브러리를 제공합니다. 새로운 데코레이터 @observable을 소개하는 MobX 또는 새로운 템플릿 구문 “v-if”를 도입하는 Vue와 같습니다. 이벤트는 어쨌든 DOM 및 자바 스크립트 이벤트 루프가 작동하는 기본 방법입니다. 사탄 숭배자들이 그랬다고 생각합니다. Lol


답변

나는이 질문이 지금 꽤 오래되었다는 것을 알고 있지만이 답변은 여전히 ​​누군가를 도울 수 있습니다. 선언적 사용자 지정 이벤트를 추가하는 React 용 JSX pragma를 작성했습니다 : jsx-native-events .

기본적으로 onEvent<EventName>패턴을 사용하여 이벤트를 감시합니다.

<some-custom-element onEventSomeEvent={ callback }></some-custom-element>