버튼 렌더링 시 양식 이벤트 발생: React 렌더링 프로세스의 성가신 문제
12599 단어 reactjavascript
사용자 정보를 가져와 목록으로 보여주는 웹 앱을 만들었습니다. 편집하거나 삭제하는 기능도 있습니다.
최종 코드는 here 입니다.
이슈가 뭐야?
문제는 편집 버튼이 작동하지 않는 것 같았습니다.
문제가 있는 구성 요소의 코드는 here 입니다.
코드here와 상호 작용할 수도 있습니다.
원인은 무엇입니까?
실제로 편집 버튼은 잘 작동합니다.
작동하지 않는 것처럼 보이는 이유는 구성 요소가 다시 렌더링된 후 편집 버튼onClick
이벤트가 종료되기 때문입니다.
점검
추가console.log
하고 편집 버튼을 클릭하면 어떻게 되는지 확인했습니다.
loaded! // the page loaded
editComment is now: false // initial state
// click the edit button
Edit button is clicked!
editComment is now: true
handleSave is called!
editComment is now: false
로그에 따르면 후드 아래에서 다음이 발생합니다.
실제로 편집 버튼은 잘 작동합니다.
작동하지 않는 것처럼 보이는 이유는 구성 요소가 다시 렌더링된 후 편집 버튼
onClick
이벤트가 종료되기 때문입니다.점검
추가
console.log
하고 편집 버튼을 클릭하면 어떻게 되는지 확인했습니다.loaded! // the page loaded
editComment is now: false // initial state
// click the edit button
Edit button is clicked!
editComment is now: true
handleSave is called!
editComment is now: false
로그에 따르면 후드 아래에서 다음이 발생합니다.
onClick
이벤트가 실행되고 현재 editComment
인 상태true
를 업데이트합니다. (초기 상태는 false
였습니다) handleSave
함수가 어떤 이유로 실행되고 상태 editComment
를 다시 false
로 업데이트합니다. 편집 버튼은 작동하지만 저장 버튼
handleSave
기능이 동시에 실행됩니다.이러한 일들이 매우 빠르게 일어나기 때문에 우리는 그것을 볼 수 없으며 편집 버튼이 작동하지 않는 것 같습니다.
다음 코드는 주석 구성 요소의 렌더링 부분을 단순화한 버전입니다.
render(){
return this.state.editComment ? (
<tr>
<td><form id="form1" onSubmit={this.handleSave}></form></td>
<td><input form="form1" type="text" name="name"/></td>
<td><input form="form1" type="email" name="email"/></td>
<td><input form="form1" type="text" name="body" /></td>
<td><button form="form1" type="submit">Save</button></td>
</tr>
):(
<tr>
<td />
<td>{this.state.name}</td>
<td>{this.state.email}</td>
<td>{this.state.body}</td>
<td>
<button onClick={() => this.setState({ editComment: true })}>Edit</button>
<button onClick={() => handleDelete()}>Delete</button>
</td>
</tr>
)
}
상태
editComment
는 처음에는 false
이므로 아직 form
및 저장 버튼이 없어야 합니다.기이한!
그렇다면
handleSave
함수가 호출되는 이유는 무엇입니까?다시 말하지만 구성 요소가 다시 렌더링된 후 편집 버튼의 이벤트
onClick
가 종료되기 때문입니다.사리
편집 버튼을 클릭하면
form
가 생성됩니다.편집 버튼과 저장 버튼은 비슷한 구조에 있기 때문에 React는 이 둘을 같은 유형의 DOM 요소로 간주합니다. 즉, React는 이 두 버튼을 구별할 수 없습니다.
// simplified version
// before re-render
<tr>
<td />
<td>
<button onClick={() => this.setState({ editComment: true })}>Edit</button>
<button onClick={() => handleDelete()}>Delete</button>
</td>
</tr>
// after re-render
<tr>
<td>
<form id="form1" onSubmit={this.handleSave}></form>
</td>
<td>
<button form="form1" type="submit">Save</button>
</td>
</tr>
When comparing two React DOM elements of the same type, React looks at the attributes of both, keeps the same underlying DOM node, and only updates the changed attributes.
https://reactjs.org/docs/reconciliation.html#dom-elements-of-the-same-type
따라서 편집 버튼이 소멸되지 않습니다. 그것은 거기에 남아 있고 속성과 속성이 업데이트됩니다.
말하자면 "저장"이라고 말하는
from="form1"
또는 type="submit"
와 같은 추가 속성이 있는 편집 버튼입니다.그런 다음 여전히 버튼
onClick
이 지속됩니다.버튼의
onClick
이벤트가 종료되면 버튼은 form
와 연결되어 handleSave
함수를 호출합니다.솔루션
e.preventDefault()
에 onClick
를 추가합니다.onSubmit
에서 handleSave
(= form
함수)를 호출하지 않습니다. render()
내부 조건의 기본이 되는 각 DOM에 대해 새 구성 요소를 만듭니다.컴포넌트를 다시 렌더링하면 기존 버튼(= 편집 버튼)이 업데이트되지 않고 새로운 버튼(= 저장 버튼)이 생성됩니다.
편집 버튼의 이벤트
onClick
가 더 이상 수신되지 않습니다. key
를 추가합니다.key
를 추가하여 이 두 버튼이 다르다는 것을 React에 알립니다.https://reactjs.org/docs/reconciliation.html#keys
분명히 이것은 매우 틈새 시장의 경우입니다.
테이블 레이아웃을 사용하거나 양식 항목을 외부에 배치하면
form
문제가 발생할 수 있습니다.구조를 구축할 때 접근성이나 가독성을 신중하게 고려하면 오류를 방지할 수 있습니다.
이번에 배운 교훈입니다!
감사의 말
이 문제를 명확하게 이해하기 위해 여러 웹 개발자 커뮤니티에 들어가 이것에 대해 질문했습니다.
이 문제를 해결하기 위해 저를 도와주신 커뮤니티의 분들께 진심으로 감사드립니다. 다시한번 정말 감사합니다🙏
Kohei Asai , , Brandon Tsang , 에게 특별히 감사드립니다.
Reference
이 문제에 관하여(버튼 렌더링 시 양식 이벤트 발생: React 렌더링 프로세스의 성가신 문제), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/shivchan/form-event-fires-on-button-render-a-minor-bug-in-react-s-optimization-of-performance-4ldm텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)