[reactjs] 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를 사용하여 이벤트를 시뮬레이션 할 수 있습니다. 있지만 이는 단위 테스트 용으로 설계되었습니다.

이 경우 valueLink를 사용하지 않고 플러그인에 의해 발생한 변경 이벤트를 수신하고 이에 대한 응답으로 입력 상태를 업데이트하는 것이 좋습니다. 양방향 바인딩은 다른 무엇보다 데모로 더 유용합니다. 순수한 양방향 바인딩이 대부분의 응용 프로그램에 적합하지 않으며 일반적으로 앱의 상호 작용을 설명하기 위해 더 많은 응용 프로그램 논리가 필요하다는 사실을 강조하기 위해 애드온에 포함됩니다.


답변

Grin / Dan Abramov의 답변을 확장하면 여러 입력 유형에서 작동합니다. 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);

    }

};


답변

임의의 요소에 대한 변경 이벤트를 트리거하면 추론하기 어려운 구성 요소간에 종속성이 생성됩니다. React의 단방향 데이터 흐름을 고수하는 것이 좋습니다.

React의 변경 이벤트를 트리거하는 간단한 스 니펫은 없습니다. 로직은 ChangeEventPlugin.js에서 구현되며 다양한 입력 유형 및 브라우저에 대해 서로 다른 코드 분기가 있습니다. 또한 구현 세부 사항은 React 버전에 따라 다릅니다.

나는 일을하는 react-trigger-change 를 만들었지 만 프로덕션 종속성이 아닌 테스트에 사용하도록 의도되었습니다.

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

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

CodePen


답변

onchange 이벤트를 처리하기 위해 함수를 사용하기 때문에 다음과 같이 할 수 있습니다.

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)} />
  );
 }
}