bestsource

React로 구축된 입력 요소를 프로그래밍 방식으로 채우려면 어떻게 해야 합니까?

bestsource 2023. 3. 10. 22:38
반응형

React로 구축된 입력 요소를 프로그래밍 방식으로 채우려면 어떻게 해야 합니까?

리액트로 만든 웹 사이트를 탐색하는 일을 맡고 있습니다.페이지(셀레늄 또는 모바일 웹뷰)에 javascript injection을 사용하여 입력란에 기입하여 제출하려고 합니다.이것은 다른 모든 사이트와 테크놀로지에서는 매력적으로 기능하지만, React는 매우 귀찮은 것 같습니다.

여기 샘플 코드가 있습니다.

var email = document.getElementById( 'email' );
email.value = 'example@mail.com';

I 값은 DOM 입력 요소에서 변경되지만 React는 변경 이벤트를 트리거하지 않습니다.

리액트를 업데이트하기 위해 여러 가지 방법을 시도해 봤어요

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

소용없다

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

동작하지 않다

email.onChange( event );

동작하지 않다

리액트와의 상호작용이 그렇게 어려워졌다니 믿을 수 없다.아무쪼록 잘 부탁드립니다.

감사해요.

중복 배제 입력 및 변경 이벤트 변경으로 인해 React > 15.6(React 16 포함)에서는 이 솔루션이 작동하지 않는 것 같습니다.

React 토론은 https://github.com/facebook/react/issues/10135에서 보실 수 있습니다.

여기서 권장되는 회피책은 https://github.com/facebook/react/issues/10135#issuecomment-314441175 입니다.

편리성을 위해 여기에 복사:

대신

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

사용할 수 있습니다.

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

그리고 나서.

setNativeValue(input, 'foo');
input.dispatchEvent(new Event('input', { bubbles: true }));

리액트는 리슨 중input텍스트 필드의 이벤트.

값을 변경하고 입력 이벤트를 수동으로 트리거하고 반응할 수 있습니다.onChange핸들러는 다음을 트리거합니다.

class Form extends React.Component {
  constructor(props) {
    super(props)
    this.state = {value: ''}
  }
  
  handleChange(e) {
    this.setState({value: e.target.value})
    console.log('State updated to ', e.target.value);
  }
  
  render() {
    return (
      <div>
        <input
          id='textfield'
          value={this.state.value}
          onChange={this.handleChange.bind(this)}
        />
        <p>{this.state.value}</p>
      </div>      
    )
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('app')
)

document.getElementById('textfield').value = 'foo'
const event = new Event('input', { bubbles: true })
document.getElementById('textfield').dispatchEvent(event)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app'></div>

다음은 입력, 선택, 확인란 등에 대한 가장 깨끗한 해결책입니다(반응 입력에만 해당되지 않음).

/**
 * See [Modify React Component's State using jQuery/Plain Javascript from Chrome Extension](https://stackoverflow.com/q/41166005)
 * See https://github.com/facebook/react/issues/11488#issuecomment-347775628
 * See [How to programmatically fill input elements built with React?](https://stackoverflow.com/q/40894637)
 * See https://github.com/facebook/react/issues/10135#issuecomment-401496776
 *
 * @param {HTMLInputElement | HTMLSelectElement} el
 * @param {string} value
 */
function setNativeValue(el, value) {
  const previousValue = el.value;

  if (el.type === 'checkbox' || el.type === 'radio') {
    if ((!!value && !el.checked) || (!!!value && el.checked)) {
      el.click();
    }
  } else el.value = value;

  const tracker = el._valueTracker;
  if (tracker) {
    tracker.setValue(previousValue);
  }

  // 'change' instead of 'input', see https://github.com/facebook/react/issues/11488#issuecomment-381590324
  el.dispatchEvent(new Event('change', { bubbles: true }));
}

사용방법:

setNativeValue(document.getElementById('name'), 'Your name');
document.getElementById('radio').click(); // or setNativeValue(document.getElementById('radio'), true)
document.getElementById('checkbox').click(); // or setNativeValue(document.getElementById('checkbox'), true)

입력 요소에는 이름을 가진 속성이 있습니다.__reactEventHandlers$...이 기능에는 다음과 같은 몇 가지 기능이 있습니다.onChange.

이것은 그 기능을 찾아 트리거하는 데 효과가 있었다.

let getReactEventHandlers = (element) => {
    // the name of the attribute changes, so we find it using a match.
    // It's something like `element.__reactEventHandlers$...`
    let reactEventHandlersName = Object.keys(element)
       .filter(key => key.match('reactEventHandler'));
    return element[reactEventHandlersName];
}

let triggerReactOnChangeEvent = (element) => {
    let ev = new Event('change');
    // workaround to set the event target, because `ev.target = element` doesn't work
    Object.defineProperty(ev, 'target', {writable: false, value: element});
    getReactEventHandlers(element).onChange(ev);
}

input.value = "some value";
triggerReactOnChangeEvent(input);

요소 ID가 없는 경우:

export default function SomeComponent() {
    const inputRef = useRef();
    const [address, setAddress] = useState("");
    const onAddressChange = (e) => {
        setAddress(e.target.value);
    }
    const setAddressProgrammatically = (newValue) => {
        const event = new Event('change', { bubbles: true });
        const input = inputRef.current;
        if (input) {
            setAddress(newValue);
            input.value = newValue;
            input.dispatchEvent(event);
        }
    }
    return (
        ...
        <input ref={inputRef} type="text" value={address} onChange={onAddressChange}/>
        ...
    );
}

React 17은 파이버와 함께 작동합니다.

function findReact(dom) {
    let key = Object.keys(dom).find(key => key.startsWith("__reactFiber$"));
    let internalInstance = dom[key];
    if (internalInstance == null) return "internalInstance is null: " + key;

    if (internalInstance.return) { // react 16+
        return internalInstance._debugOwner
            ? internalInstance._debugOwner.stateNode
           : internalInstance.return.stateNode;
    } else { // react <16
        return internalInstance._currentElement._owner._instance;
   }
}

그 후, 다음과 같이 합니다.

findReact(domElement).onChangeWrapper("New value");

여기서 domElement는 변경하려는 필드의 data-param-name을 가진 tr입니다.

var domElement = ?.querySelectorAll('tr[data-param-name="<my field name>"]')

언급URL : https://stackoverflow.com/questions/40894637/how-to-programmatically-fill-input-elements-built-with-react

반응형