Programing

react js에서 onchange 이벤트를 트리거하는 가장 좋은 방법은 무엇입니까?

lottogame 2020. 9. 23. 08:02
반응형

react js에서 onchange 이벤트를 트리거하는 가장 좋은 방법은 무엇입니까?


Backbone + ReactJS 번들을 사용하여 클라이언트 측 앱을 빌드합니다. 악명 높은 것에 크게 의존하여 valueLink양방향 바인딩을 위해 ReactJS 인터페이스를 지원하는 자체 래퍼를 통해 모델에 직접 값을 전파합니다.

이제 우리는 문제에 직면했습니다.

우리는이 jquery.mask.js프로그램 따라서 화재 이벤트를 반응하지 않는 입력 값의 형식을 플러그인. 이 모든 것이 모델이 사용자 입력에서 형식화되지 않은 값을 수신 하고 플러그인 에서 형식화 된 값을 놓치는 상황으로 이어집니다 .

React는 브라우저에 따라 많은 이벤트 처리 전략을 가지고있는 것 같습니다. React가 그것을 듣도록 특정 DOM 요소에 대한 변경 이벤트를 트리거하는 일반적인 방법이 있습니까?


React 16 및 React> = 15.6의 경우

.value=React 라이브러리가 입력 값 setter를 재정의하기 때문에 Setter 가 원하는대로 작동하지 않지만 inputas 컨텍스트 에서 직접 함수를 호출 할 수 있습니다 .

var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
nativeInputValueSetter.call(input, 'react 16 value');

var ev2 = new Event('input', { bubbles: true});
input.dispatchEvent(ev2);

textarea 요소 prototype의 경우 HTMLTextAreaElement클래스 를 사용해야합니다 .

새로운 코드 펜 예제 .

이 기여자그의 솔루션에 대한 모든 크레딧

React <= 15.5에 대한 오래된 답변

으로 react-dom ^15.6.0당신이 사용할 수있는 simulated이벤트가 통과하는 이벤트 객체에 플래그를

var ev = new Event('input', { bubbles: true});
ev.simulated = true;
element.value = 'Something new';
element.dispatchEvent(ev);

예제코드 펜을 만들었습니다.

새 플래그가 필요한 이유를 이해하기 위해이 주석이 매우 유용 하다는 것을 알았습니다 .

React의 입력 로직은 이제 값당 두 번 이상 발생하지 않도록 변경 이벤트의 중복을 제거합니다. 브라우저 onChange / onInput 이벤트와 DOM 노드 값 소품에 대한 설정을 모두 수신합니다 (JavaScript를 통해 값을 업데이트 할 때). 이것은 입력의 값을 수동으로 업데이트하면 input.value = 'foo'다음 {target : input}로 ChangeEvent를 전달한다는 의미의 부작용이 있습니다. React는 세트와 이벤트를 모두 등록합니다. 값이 여전히` 'foo인지 확인합니다. ', 중복 이벤트로 간주하고 삼키십시오.

이것은 "실제"브라우저에서 시작된 이벤트가 element.value에 대한 집합을 트리거하지 않기 때문에 정상적인 경우에 잘 작동합니다. 시뮬레이션 된 플래그로 트리거 한 이벤트에 태그를 지정하여이 논리를 비밀리에 탈출 할 수 있으며 반응은 항상 이벤트를 발생시킵니다. https://github.com/jquense/react/blob/9a93af4411a8e880bbc05392ccf2b195c97502d1/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js#L128


적어도 텍스트 입력에서는 onChange입력 이벤트를 수신 하는 것처럼 보입니다 .

var event = new Event('input', { bubbles: true });
element.dispatchEvent(event);

이 답변이 조금 늦게 오는 것을 알고 있지만 최근 비슷한 문제에 직면했습니다. 중첩 된 구성 요소에서 이벤트를 트리거하고 싶었습니다. 라디오 및 체크 박스 유형 위젯 (체크 박스 및 / 또는 라디오 버튼처럼 작동하는 div)이 포함 된 목록이 있었고 애플리케이션의 다른 위치에서 누군가가 도구 상자를 닫으면 하나의 선택을 취소해야했습니다.

나는 이것이 모범 사례인지 확실하지 않지만 매우 간단한 해결책을 찾았지만 작동합니다.

var event = new MouseEvent('click', {
 'view': window, 
 'bubbles': true, 
 'cancelable': false
});
var node = document.getElementById('nodeMyComponentsEventIsConnectedTo');
node.dispatchEvent(event);

이것은 domNode에서 클릭 이벤트를 트리거하고 react를 통해 연결된 핸들러가 실제로 호출되었으므로 누군가가 요소를 클릭하면 예상하는 것처럼 작동합니다. 나는 onChange를 테스트하지 않았지만 작동해야하며 이것이 실제로 오래된 버전의 IE에서 어떻게 공정 할 지 확실하지 않지만 MouseEvent는 적어도 IE9 이상에서 지원된다고 생각합니다.

내 구성 요소가 매우 작기 때문에 (내 응용 프로그램의 일부만 사용되었으므로 여전히 학습 중이므로) dom 노드에 대한 참조를 얻지 않고도 다른 방법으로 동일한 작업을 수행 할 수 있었기 때문에 결국 특정 사용 사례에서 멀어졌습니다.

최신 정보:

다른 사람들이 주석에서 언급했듯이 this.refs.refnamedom 노드에 대한 참조를 얻는 데 사용하는 것이 좋습니다 . 이 경우 refname은를 통해 구성 요소에 연결 한 참조 <MyComponent ref='refname' />입니다.


ReactTestUtils를 사용하여 이벤트를 시뮬레이션 할 수 있지만 이는 단위 테스트 용으로 설계되었습니다.

I'd recommend not using valueLink for this case and simply listening to change events fired by the plugin and updating the input's state in response. The two-way binding utils more as a demo than anything else; they're included in addons only to emphasize the fact that pure two-way binding isn't appropriate for most applications and that you usually need more application logic to describe the interactions in your app.


Triggering change events on arbitrary elements creates dependencies between components which are hard to reason about. It's better to stick with React's one-way data flow.

There is no simple snippet to trigger React's change event. The logic is implemented in ChangeEventPlugin.js and there are different code branches for different input types and browsers. Moreover, the implementation details vary across versions of React.

I have built react-trigger-change that does the thing, but it is intended to be used for testing, not as a production dependency:

let node;
ReactDOM.render(
  <input
    onChange={() => console.log('changed')}
    ref={(input) => { node = input; }}
  />,
  mountNode
);

reactTriggerChange(node); // 'changed' is logged

CodePen


Expanding on the answer from Grin/Dan Abramov, this works across multiple input types. Tested in React >= 15.5

const inputTypes = [
    window.HTMLInputElement,
    window.HTMLSelectElement,
    window.HTMLTextAreaElement,
];

export const triggerInputChange = (node, value = '') => {

    // only process the change on elements we know have a value setter in their constructor
    if ( inputTypes.indexOf(node.__proto__.constructor) >-1 ) {

        const setValue = Object.getOwnPropertyDescriptor(node.__proto__, 'value').set;
        const event = new Event('input', { bubbles: true });

        setValue.call(node, value);
        node.dispatchEvent(event);

    }

};

well since we use functions to handle an onchange event, we can do it like this:

class Form extends Component {
 constructor(props) {
  super(props);
  this.handlePasswordChange = this.handlePasswordChange.bind(this);
  this.state = { password: '' }
 }

 aForceChange() {
  // something happened and a passwordChange
  // needs to be triggered!!

  // simple, just call the onChange handler
  this.handlePasswordChange('my password');
 }

 handlePasswordChange(value) {
 // do something
 }

 render() {
  return (
   <input type="text" value={this.state.password} onChange={changeEvent => this.handlePasswordChange(changeEvent.target.value)} />
  );
 }
}

I found this on React's Github issues: Works like a charm (v15.6.2)

Here is how I implemented to a Text input:

changeInputValue = newValue => {

    const e = new Event('input', { bubbles: true })
    const input = document.querySelector('input[name=' + this.props.name + ']')
    console.log('input', input)
    this.setNativeValue(input, newValue)
    input.dispatchEvent(e)
  }

  setNativeValue (element, value) {
    const valueSetter = Object.getOwnPropertyDescriptor(element, 'value').set
    const prototype = Object.getPrototypeOf(element)
    const prototypeValueSetter = Object.getOwnPropertyDescriptor(
      prototype,
      'value'
    ).set

    if (valueSetter && valueSetter !== prototypeValueSetter) {
      prototypeValueSetter.call(element, value)
    } else {
      valueSetter.call(element, value)
    }
  }

If you are using Backbone and React, I'd recommend one of the following,

They both help integrate Backbone models and collections with React views. You can use Backbone events just like you do with Backbone views. I've dabbled in both and didn't see much of a difference except one is a mixin and the other changes React.createClass to React.createBackboneClass.

참고URL : https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-onchange-event-in-react-js

반응형