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
'bestsource' 카테고리의 다른 글
JSON을 사용하여 XmlHttpRequest POST 작성 (0) | 2023.03.10 |
---|---|
JSON 데이터의 동적 형식(다른 유형) (0) | 2023.03.10 |
제목 직후에 커스텀 투고 유형 편집 화면에 버튼/링크 추가 (0) | 2023.03.10 |
여러 시스템의 일원화된 사용자 관리 시스템을 위한 최적의 솔루션 (0) | 2023.03.10 |
Angular-Translate를 사용하여 HTML을 포함하는 문자열을 처리하는 방법 (0) | 2023.03.10 |