[javascript] 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가 뷰를 방해하지 않고 다시 생성하지 않고 재사용하도록 지시합니다. 그러면 초점이 맞춰진 항목이 초점을 유지해야합니다.


답변

나는 계속 여기로 돌아와서 항상 다른 곳에서 해결책을 찾습니다. 그래서 나는 이것을 다시 잊을 것이라는 것을 알고 있기 때문에 여기에 그것을 문서화 할 것입니다!

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


답변

A는 라우터 반응 내에서 문제가 있다면 <Route/>사용 render하는 대신 소품 component.

<Route path="/user" render={() => <UserPage/>} />

초점 손실은 component소품 React.createElement이 변경 사항을 다시 렌더링하는 대신 매번 사용 하기 때문에 발생합니다 .

세부 정보 : https://reacttraining.com/react-router/web/api/Route/component


답변

내 대답은 @ z5h가 말한 것과 비슷합니다.

제 경우에는 Math.random()key 에는 구성 요소에 대해 고유 한 것을 생성했습니다 .

key해당 배열의 모든 구성 요소를 다시 렌더링하는 대신 해당 특정 구성 요소에 대한 다시 렌더링을 트리거하는 데만 사용 된다고 생각했습니다 (코드에서 구성 요소의 배열을 반환합니다). 다시 렌더링 후 상태를 복원하는 데 사용되는지 몰랐습니다.

그것을 제거하면 나를 위해 일했습니다.


답변

요소에 autoFocus속성을 적용하면 input집중해야하는 입력이 하나만있는 상황에서 해결 방법으로 수행 할 수 있습니다. 이 경우 key속성은 하나의 요소 일 뿐이므로 input기본 구성 요소의 다시 렌더링에 대한 초점을 잃지 않도록 요소를 자체 구성 요소로 분리하는 것에 대해 걱정할 필요가 없습니다 .


답변

나는 같은 행동을했다.

내 코드의 문제는 다음과 같이 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>
);


답변

방금이 문제가 발생하여 여기에 도움을 요청했습니다. CSS를 확인하십시오! 입력 필드가있을 수 없거나 user-select: none;iPad에서 작동하지 않습니다.