React.js-다시 렌더링 할 때 입력 포커스가 손실 됨
나는 단지 텍스트 입력에 쓰고 있고 onChange
내가 호출하는 setState
경우에 React가 내 UI를 다시 렌더링합니다. 문제는 텍스트 입력이 항상 포커스를 잃기 때문에 각 문자에 대해 다시 포커스가 필요하다는 것입니다. : D.
var EditorContainer = React.createClass({
componentDidMount: function () {
$(this.getDOMNode()).slimScroll({height: this.props.height, distance: '4px', size: '8px'});
},
componentDidUpdate: function () {
console.log("zde");
$(this.getDOMNode()).slimScroll({destroy: true}).slimScroll({height: 'auto', distance: '4px', size: '8px'});
},
changeSelectedComponentName: function (e) {
//this.props.editor.selectedComponent.name = $(e.target).val();
this.props.editor.forceUpdate();
},
render: function () {
var style = {
height: this.props.height + 'px'
};
return (
<div className="container" style={style}>
<div className="row">
<div className="col-xs-6">
{this.props.selected ? <h3>{this.props.selected.name}</h3> : ''}
{this.props.selected ? <input type="text" value={this.props.selected.name} onChange={this.changeSelectedComponentName} /> : ''}
</div>
<div className="col-xs-6">
<ComponentTree editor={this.props.editor} components={this.props.components}/>
</div>
</div>
</div>
);
}
});
나머지 코드를 보지 않고는 추측입니다. EditorContainer를 만들 때 구성 요소에 대한 고유 키를 지정합니다.
<EditorContainer key="editor1"/>
다시 렌더링이 발생할 때 동일한 키가 표시되면 React가 뷰를 방해하지 않고 다시 생성하지 않고 재사용하도록 지시합니다. 그러면 초점이 맞춰진 항목이 초점을 유지해야합니다.
A는 라우터 반응 내에서 문제가 있다면 <Route/>
사용 render
하는 대신 소품 component
.
<Route path="/user" render={() => <UserPage/>} />
초점 손실은 component
소품 React.createElement
이 변경 사항을 다시 렌더링하는 대신 매번 사용 하기 때문에 발생합니다 .
세부 정보 : https://reacttraining.com/react-router/web/api/Route/component
나는 계속 여기로 돌아와서 항상 다른 곳에서 해결책을 찾습니다. 그래서 나는 이것을 다시 잊을 것이라는 것을 알고 있기 때문에 여기에 그것을 문서화 할 것입니다!
제 input
경우에 초점을 잃은 이유 는 input
온 상태 변경을 다시 렌더링했기 때문 입니다.
버기 코드 :
import React from 'react';
import styled from 'styled-components';
class SuperAwesomeComp extends React.Component {
state = {
email: ''
};
updateEmail = e => {
e.preventDefault();
this.setState({ email: e.target.value });
};
render() {
const Container = styled.div``;
const Input = styled.input``;
return (
<Container>
<Input
type="text"
placeholder="Gimme your email!"
onChange={this.updateEmail}
value={this.state.email}
/>
</Container>
)
}
}
그래서 문제는 제가 항상 모든 것을 한곳에서 코딩하기 시작하여 빠르게 테스트하고 나중에 모든 것을 별도의 모듈로 분리한다는 것입니다. 그러나 입력 변경시 상태를 업데이트하면 렌더링 기능이 트리거되고 포커스가 손실되기 때문에이 전략은 역효과를냅니다.
수정은 간단합니다. 처음부터 모듈화를 수행합니다. 즉, " Input
구성 요소를 render
기능 밖으로 이동 "합니다.
고정 코드
import React from 'react';
import styled from 'styled-components';
const Container = styled.div``;
const Input = styled.input``;
class SuperAwesomeComp extends React.Component {
state = {
email: ''
};
updateEmail = e => {
e.preventDefault();
this.setState({ email: e.target.value });
};
render() {
return (
<Container>
<Input
type="text"
placeholder="Gimme your email!"
onChange={this.updateEmail}
value={this.state.email}
/>
</Container>
)
}
}
Ref. 솔루션 : https://github.com/styled-components/styled-components/issues/540#issuecomment-283664947
내 대답은 @ z5h가 말한 것과 비슷합니다.
제 경우 에는 구성 요소에 Math.random()
대한 고유 항목을 생성했습니다 key
.
key
해당 배열의 모든 구성 요소를 다시 렌더링하는 대신 해당 특정 구성 요소에 대한 다시 렌더링을 트리거하는 데만 사용 된다고 생각했습니다 (코드에서 구성 요소의 배열을 반환합니다). 다시 렌더링 후 상태를 복원하는 데 사용되는지 몰랐습니다.
그것을 제거하면 나를 위해 일했습니다.
추신 : 나는 이것에 대해 언급 할 수 있었지만 그것에 대한 평판이 충분하지 않습니다.
방금이 문제가 발생하여 여기에 도움을 요청했습니다. CSS를 확인하십시오! 입력 필드가있을 수 없거나 user-select: none;
iPad에서 작동하지 않습니다.
나는 같은 행동을했다.
내 코드의 문제는 다음과 같이 jsx 요소의 중첩 배열을 생성했다는 것입니다.
const example = [
[
<input value={'Test 1'}/>,
<div>Test 2</div>,
<div>Test 3</div>,
]
]
...
render = () => {
return <div>{ example }</div>
}
이 중첩 배열의 모든 요소는 부모 요소를 업데이트 할 때마다 다시 렌더링됩니다. 따라서 입력은 매번 "ref"prop을 잃습니다.
내부 배열을 반응 구성 요소로 변환하는 문제 (렌더링 기능이있는 함수)를 수정했습니다.
const example = [
<myComponentArray />
]
...
render = () => {
return <div>{ example }</div>
}
편집하다:
중첩을 만들 때 동일한 문제가 나타납니다. React.Fragment
const SomeComponent = (props) => (
<React.Fragment>
<label ... />
<input ... />
</React.Fragment>
);
const ParentComponent = (props) => (
<React.Fragment>
<SomeComponent ... />
<div />
</React.Fragment>
);
요소에 autoFocus
속성을 적용하면 input
집중해야하는 입력이 하나 뿐인 상황에서 해결 방법으로 수행 할 수 있습니다. 이 경우 key
속성은 하나의 요소 일 뿐이므로 input
기본 구성 요소의 다시 렌더링에 대한 초점을 잃지 않도록 요소를 자체 구성 요소로 분리하는 것에 대해 걱정할 필요가 없습니다 .
핵심 이유는 React가 다시 렌더링 할 때 이전 DOM 참조가 유효하지 않기 때문입니다. 반응이 DOM 트리를 변경하고 여기에 입력이 더 이상 존재하지 않기 때문에 this.refs.input.focus가 작동하지 않음을 의미합니다.
제공된 답변은 도움이되지 않았습니다. 여기에 제가 한 일이 있지만 독특한 상황이있었습니다.
코드를 정리하기 위해 구성 요소를 다른 파일로 가져올 준비가 될 때까지이 형식을 사용하는 경향이 있습니다.
render(){
const MyInput = () => {
return <input onChange={(e)=>this.setState({text: e.target.value}) />
}
return(
<div>
<MyInput />
</div>
)
그러나 이로 인해 초점을 잃게되었고 코드를 div에 직접 넣었을 때 작동했습니다.
return(
<div>
<input onChange={(e)=>this.setState({text: e.target.value}) />
</div>
)
나는 이것이 왜 그런지 모르겠다. 이것이 내가 이런 식으로 작성하면서 가진 유일한 문제이고 내가 가진 대부분의 파일에서 그것을 수행하지만 누군가 비슷한 일을한다면 이것이 초점을 잃는 이유입니다.
나에게 이것은 검색 결과 목록과 동일한 구성 요소 (UserList라고 함) 에서 렌더링되는 검색 입력 상자로 인해 발생했습니다 . 따라서 검색 결과가 변경 될 때마다 입력 상자를 포함하여 전체 UserList 구성 요소가 다시 렌더링되었습니다.
내 솔루션이라는 새로운 구성 요소를 만드는 것이 었습니다 UserListSearch 별도로 UserList에를 . 이 작업을 수행하기 위해 UserListSearch의 입력 필드에 키를 설정할 필요가 없습니다. 내 UsersContainer의 렌더링 기능은 이제 다음과 같습니다.
class UserContainer extends React.Component {
render() {
return (
<div>
<Route
exact
path={this.props.match.url}
render={() => (
<div>
<UserListSearch
handleSearchChange={this.handleSearchChange}
searchTerm={this.state.searchTerm}
/>
<UserList
isLoading={this.state.isLoading}
users={this.props.users}
user={this.state.user}
handleNewUserClick={this.handleNewUserClick}
/>
</div>
)}
/>
</div>
)
}
}
바라건대 이것은 누군가에게 도움이되기를 바랍니다.
열에 입력 텍스트 줄이있는 html 테이블에서 동일한 문제가 발생했습니다. 루프 내부에서 json 객체를 읽고 특히 입력 텍스트가있는 열이있는 행을 만듭니다.
http://reactkungfu.com/2015/09/react-js-loses-input-focus-on-typing/
나는 다음과 같은 방법으로 그것을 해결할 수 있었다.
import { InputTextComponent } from './InputTextComponent';
//import my inputTextComponent
...
var trElementList = (function (list, tableComponent) {
var trList = [],
trElement = undefined,
trElementCreator = trElementCreator,
employeeElement = undefined;
// iterating through employee list and
// creating row for each employee
for (var x = 0; x < list.length; x++) {
employeeElement = list[x];
var trNomeImpatto = React.createElement('tr', null, <td rowSpan="4"><strong>{employeeElement['NomeTipologiaImpatto'].toUpperCase()}</strong></td>);
trList.push(trNomeImpatto);
trList.push(trElementCreator(employeeElement, 0, x));
trList.push(trElementCreator(employeeElement, 1, x));
trList.push(trElementCreator(employeeElement, 2, x));
} // end of for
return trList; // returns row list
function trElementCreator(obj, field, index) {
var tdList = [],
tdElement = undefined;
//my input text
var inputTextarea = <InputTextComponent
idImpatto={obj['TipologiaImpattoId']}//index
value={obj[columns[field].nota]}//initial value of the input I read from my json data source
noteType={columns[field].nota}
impattiComposite={tableComponent.state.impattiComposite}
//updateImpactCompositeNote={tableComponent.updateImpactCompositeNote}
/>
tdElement = React.createElement('td', { style: null }, inputTextarea);
tdList.push(tdElement);
var trComponent = createClass({
render: function () {
return React.createElement('tr', null, tdList);
}
});
return React.createElement(trComponent);
} // end of trElementCreator
});
...
//my tableComponent
var tableComponent = createClass({
// initial component states will be here
// initialize values
getInitialState: function () {
return {
impattiComposite: [],
serviceId: window.sessionStorage.getItem('serviceId'),
serviceName: window.sessionStorage.getItem('serviceName'),
form_data: [],
successCreation: null,
};
},
//read a json data soure of the web api url
componentDidMount: function () {
this.serverRequest =
$.ajax({
url: Url,
type: 'GET',
contentType: 'application/json',
data: JSON.stringify({ id: this.state.serviceId }),
cache: false,
success: function (response) {
this.setState({ impattiComposite: response.data });
}.bind(this),
error: function (xhr, resp, text) {
// show error to console
console.error('Error', xhr, resp, text)
alert(xhr, resp, text);
}
});
},
render: function () {
...
React.createElement('table', {style:null}, React.createElement('tbody', null,trElementList(this.state.impattiComposite, this),))
...
}
//my input text
var inputTextarea = <InputTextComponent
idImpatto={obj['TipologiaImpattoId']}//index
value={obj[columns[field].nota]}//initial value of the input I read //from my json data source
noteType={columns[field].nota}
impattiComposite={tableComponent.state.impattiComposite}//impattiComposite = my json data source
/>//end my input text
tdElement = React.createElement('td', { style: null }, inputTextarea);
tdList.push(tdElement);//add a component
//./InputTextComponent.js
import React from 'react';
export class InputTextComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
idImpatto: props.idImpatto,
value: props.value,
noteType: props.noteType,
_impattiComposite: props.impattiComposite,
};
this.updateNote = this.updateNote.bind(this);
}
//Update a inpute text with new value insert of the user
updateNote(event) {
this.setState({ value: event.target.value });//update a state of the local componet inputText
var impattiComposite = this.state._impattiComposite;
var index = this.state.idImpatto - 1;
var impatto = impattiComposite[index];
impatto[this.state.noteType] = event.target.value;
this.setState({ _impattiComposite: impattiComposite });//update of the state of the father component (tableComponet)
}
render() {
return (
<input
className="Form-input"
type='text'
value={this.state.value}
onChange={this.updateNote}>
</input>
);
}
}
내가 this
다시 렌더링하도록 만든 구성 요소 에 바인딩 하고 있었던 것으로 밝혀졌습니다.
다른 사람이이 문제를 겪을 경우를 대비하여 여기에 게시 할 것이라고 생각했습니다.
나는 변해야했다
<Field
label="Post Content"
name="text"
component={this.renderField.bind(this)}
/>
에
<Field
label="Post Content"
name="text"
component={this.renderField}
/>
내 경우에는 이후 간단한 수정, 사실은 필요가 없었다 this
에서 renderField
, 그러나 희망 나 다른이의 의지 도움말 사람을 게시.
나는 value
소품을 defaultValue
. 그것은 나를 위해 작동합니다.
...
// before
<input value={myVar} />
// after
<input defaultValue={myVar} />
내 문제는 항목 값을 사용하여 동적으로 키 이름을 지정했다는 것입니다. 제 경우에는 "name"이므로 키는 key = { ${item.name}-${index}
}입니다. 따라서 item.name을 값으로 사용하여 입력을 변경하고 싶을 때 키도 변경되므로 반응이 해당 요소를 인식하지 못합니다.
참고URL : https://stackoverflow.com/questions/22573494/react-js-input-losing-focus-when-rerendering
'Program Tip' 카테고리의 다른 글
XAML에서 테두리에 대한 MouseOver 이벤트 / 트리거를 설정하는 방법은 무엇입니까? (0) | 2020.10.29 |
---|---|
IFRAME 및 iPad의 Safari, 사용자는 콘텐츠를 어떻게 스크롤 할 수 있습니까? (0) | 2020.10.29 |
Java에서 Temp 파일을 만드는 안전한 방법은 무엇입니까? (0) | 2020.10.29 |
네임 스페이스 내의 모든 클래스를 얻으려면 어떻게해야합니까? (0) | 2020.10.29 |
apt 저장소를 신뢰하는 방법 : Debian apt-get 업데이트 오류 공개 키를 사용할 수 없습니다 : NO_PUBKEY (0) | 2020.10.29 |