programing

React.js - 재렌더 시 입력이 초점을 잃음

bestprogram 2023. 3. 18. 09:31

React.js - 재렌더 시 입력이 초점을 잃음

요.onChange : ★★★★★★★setState반응하다. 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>
        );
    }

});

나머지 코드를 보지 않고 추측할 수 있습니다.Editor Container를 생성할 때 구성 요소에 대한 고유한 키를 지정하십시오.

<EditorContainer key="editor1"/>

재렌더링이 발생했을 때 같은 키가 나타나면 React에 Clobber하지 말고 보기를 재생성하지 말고 재사용하라는 메시지가 다시 표시됩니다.그러면 초점을 맞춘 항목이 계속 초점을 맞춰야 합니다.

나는 계속해서 이곳에 돌아오고 항상 마지막에 다른 곳에 대한 해결책을 찾는다.다시 잊어버릴 것 같아서 여기서 기록하겠습니다!

★★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>
    )
  }
}

문제는 항상 모든 것을 한 곳에서 코딩하여 빠르게 테스트하고 나중에 다른 모듈로 분할한다는 것입니다.그러나 이 전략은 입력 변경 시 상태를 업데이트하면 렌더링 기능이 트리거되고 포커스가 손실되기 때문에 역효과를 가져옵니다.

, '를 처음부터 모듈화를 수행합니다.즉, 다음과 같습니다.Inputrender

고정 코드

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

솔루션 참조: https://github.com/styled-components/styled-components/issues/540#issuecomment-283664947

<Route/> render 소품component.

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


은, 「중요」가입니다.component는 ""를 사용합니다.React.createElement매번 변경 사항을 다시 적용하는 대신 말이죠.

자세한 내용은 이쪽:https://reacttraining.com/react-router/web/api/Route/component

갈고리와 같은 증상이 있었어요.하지만 문제는 부모 내부의 컴포넌트를 정의하는 것이었습니다.

틀렸다:

const Parent =() => {
    const Child = () => <p>Child!</p>
    return <Child />
}

오른쪽:

const Child = () => <p>Child!</p>
const Parent = () => <Child />

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

경우에는 ★★★★★★★★★★★★★★★★★★★★★★.Math.random()한 것을 내다key컴포넌트용입니다.

는 ★★★★★★★★★★★★★★★★★★★★★★★★★key는 특정 컴포넌트의 리렌더를 트리거하기 위해서만 사용되며, 어레이 내의 모든 컴포넌트를 리렌더하는 경우는 없습니다(코드로 컴포넌트 배열을 반환합니다).재렌더링 후 상태 회복에 사용되는지 몰랐습니다.

그걸 없앤 게 나한테는 효과가 있었어.

의 적용autoFocus input요소는 초점을 맞출 필요가 있는 입력이1개뿐인 상황에서 회피책으로 기능합니다. a는 a, a는 a, a, a는 a, a, a는 a, akey이기 때문에 만 아니라 input주요 구성 요소의 재조정에 초점을 잃지 않도록 요소를 자체 구성 요소로 변환합니다.

가 한 '아까'를 이다.value을 대다defaultValue 두 변경은 두두 and and and and 。onChange to event event event 。onBlur.

저도 같은 행동을 했어요.

코드의 문제는 다음과 같은 jsx 요소의 중첩된 배열을 작성한 것입니다.

const example = [
            [
                <input value={'Test 1'}/>,
                <div>Test 2</div>,
                <div>Test 3</div>,
            ]
        ]

...

render = () => {
    return <div>{ example }</div>
}

이 중첩된 배열의 모든 요소는 상위 요소를 업데이트할 때마다 다시 렌더링됩니다.따라서 입력이 매번 "ref" 프로포트를 잃게 됩니다.

내부 어레이를 반응 컴포넌트로 변환하는 문제를 수정했습니다(렌더 기능이 있는 함수).

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

입력의 키 속성 및 부모 요소를 삭제하는 동일한 문제를 해결했습니다.

// Before
<input
    className='invoice_table-input invoice_table-input-sm'
    type='number'
    key={ Math.random }
    defaultValue={pageIndex + 1}
    onChange={e => {
        const page = e.target.value ? Number(e.target.value) - 1 : 0
        gotoPage(page)
    }}
/>
// After
<input
    className='invoice_table-input invoice_table-input-sm'
    type='number'
    defaultValue={pageIndex + 1}
    onChange={e => {
        const page = e.target.value ? Number(e.target.value) - 1 : 0
        gotoPage(page)
    }}
/>

제공된 답변은 도움이 되지 않았습니다. 제가 한 일은 이렇습니다만, 저는 독특한 상황이 있었습니다.

코드를 정리하기 위해 컴포넌트를 다른 파일로 가져올 준비가 될 때까지 이 형식을 사용하는 경향이 있습니다.

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>
)

왜 그런지 모르겠어요.이렇게 쓰는 데 문제가 생긴 건 이것뿐이에요.제가 가지고 있는 대부분의 파일에서는 이 작업을 하고 있습니다만, 같은 작업을 하고 있는 사람이 있으면, 그 때문에 포커스가 흐트러집니다.

가 다른 컨테이너 ) (즉, 요소)는 다음과 같습니다.<div key={"bart"}...><input key={"lisa"}...> ... </input></div>-- 생략된 코드를 나타내는 줄임표는 컨테이너 요소(입력 필드뿐만 아니라)에 고유하고 일정한 키가 있어야 합니다.그렇지 않으면 React는 자녀의 상태가 업데이트될 때 단순히 이전 컨테이너를 다시 렌더링하는 것이 아니라 완전히 새로운 컨테이너 요소를 렌더링합니다.논리적으로는 하위 요소만 업데이트해야 하지만...

많은 주소 정보를 가지고 있는 컴포넌트를 작성하려고 하다가 문제가 발생했습니다.작업 코드는 다음과 같습니다.

// import react, components
import React, { Component } from 'react'

// import various functions
import uuid from "uuid";

// import styles
import "../styles/signUp.css";

export default class Address extends Component {
  constructor(props) {
    super(props);
    this.state = {
      address1: "",
      address2: "",
      address1Key: uuid.v4(),
      address2Key: uuid.v4(),
      address1HolderKey: uuid.v4(),
      address2HolderKey: uuid.v4(),
      // omitting state information for additional address fields for brevity
    };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    event.preventDefault();
    this.setState({ [`${event.target.id}`]: event.target.value })
  }

  render() {
    return (
      <fieldset>
        <div className="labelAndField" key={this.state.address1HolderKey} >
          <label className="labelStyle" for="address1">{"Address"}</label>
          <input className="inputStyle"
            id="address1"
            name="address1"
            type="text"
            label="address1"
            placeholder=""
            value={this.state.address1}
            onChange={this.handleChange}
            key={this.state.address1Key} ></input >
        </div> 
        <div className="labelAndField" key={this.state.address2HolderKey} >
          <label className="labelStyle" for="address2">{"Address (Cont.)"}</label>
          <input className="inputStyle"
            id="address2"
            name="address2"
            type="text"
            label="address2"
            placeholder=""
            key={this.state.address2Key} ></input >
        </div>
        {/* omitting rest of address fields for brevity */}
      </fieldset>
    )
  }
}

날카로운 눈을 가진 독자들은 주의할 것이다.<fieldset>포함 요소이지만 키가 필요하지 않습니다.이 일어나다<>그리고.<React.Fragment>또는 심지어<div>왜요? 아마 바로 옆에 있는 컨테이너만 열쇠가 필요할 거예요.나도 몰라.수학 교과서에서 말하는 것처럼, 설명은 독자들에게 연습으로 남겨진다.

이 문제가 있었습니다만, 기능 컴포넌트를 사용하고 있어 부모 컴포넌트의 상태와 링크하고 있는 것이 문제였습니다.클래스 컴포넌트를 사용하는 것으로 바꾸면 문제가 없어집니다.기능 컴포넌트를 사용할 때 간단한 아이템 렌더러 등에게 훨씬 편리하기 때문에 이 문제를 해결할 방법이 있기를 바랍니다.

저는 이 문제에 부딪혀 도움을 청하러 왔습니다.CSS 체 ! 에는 음음음음음음음음음음음을 사용할 .user-select: none;그렇지 않으면 아이패드에서는 동작하지 않습니다.

그 주된 이유는 다음과 같습니다.리액트 리렌더 시 이전 DOM 참조는 무효가 됩니다.즉, 리액트가 DOM 트리를 변경했고, 사용자는 this.refs.input을 변경했습니다.여기에 입력된 정보가 더 이상 존재하지 않기 때문에 포커스가 작동하지 않습니다.

이것은 검색 입력 상자가 검색 결과 목록과 동일한 컴포넌트(UserList라고 함)에 렌더링되었기 때문에 발생한 것입니다.따라서 검색 결과가 변경될 때마다 입력 상자를 포함한 UserList 구성 요소 전체가 다시 렌더링되었습니다.

저의 솔루션은 UserList와는 다른 UserListSearch라는 완전히 새로운 컴포넌트를 만드는 것이었습니다.User List Search의 입력 필드에 키를 설정할 필요가 없었습니다.Users Container의 렌더링 함수는 다음과 같습니다.

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

이게 누군가에게도 도움이 되길 바라.

★★★★★★★★★★★를 바꿨다.value을 대다defaultValue전 좋아요.

...
// before
<input value={myVar} />

// after
<input defaultValue={myVar} />

의 문제는 으로 키의 이 경우,는 key{{키입니다.}키입니다.${item.name}-${index}}. 으로 하여 요소가 그래서 item.name을 값으로 하여 입력을 변경하려고 하면 키도 변경되어 해당 요소가 인식되지 않습니다.

태그 입력에 다음 코드가 포함되었습니다.

ref={(input) => {
     if (input) {
         input.focus();
     }
 }}

이전:

<input
      defaultValue={email}
      className="form-control"
      type="email"
      id="email"
      name="email"
      placeholder={"mail@mail.com"}
      maxLength="15"
      onChange={(e) => validEmail(e.target.value)}
/>

그 후:

<input
     ref={(input) => {
          if (input) {
             input.focus();
          }
      }}
      defaultValue={email}
      className="form-control"
      type="email"
      id="email"
      name="email"
      placeholder={"mail@mail.com"}
      maxLength="15"
      onChange={(e) => validEmail(e.target.value)}
/>

저도 비슷한 문제가 있었는데, 이것으로 해결되었습니다.

const component = () => {
 return <input onChange={({target})=>{
    setValue(target.vlaue)
   }       
 } />
}

const ThisComponentKeptRefreshingContainer = () => {
   return(
     <component />
   )
}

const ThisContainerDidNot= () => {
   return(
     <> {component()} </>
   )
}

그러나 코드 그림에서는 컴포넌트를 엘리먼트처럼 차일드라고 부르기 때문에 함수처럼 부르면 재렌더링 효과를 얻을 수 없었습니다.도움이 되기를 바라다

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

심플한 솔루션:

<input ref={ref => ref && ref.focus()}
    onFocus={(e)=>e.currentTarget.setSelectionRange(e.currentTarget.value.length, e.currentTarget.value.length)}
    />

ref이 「」를 트리거 합니다.onFocus끝 부분을 계산하고 그에 따라 커서를 설정합니다.

이 경우 Input Container 컴포넌트와 입력 필드 자체에 Math.random()을 사용하여 설정했던 주요 소품 값이 생성되었다는 문제가 있었습니다.값의 특성이 일정하지 않아 편집 중인 입력 필드를 추적하기가 어려웠습니다.

저는 포털 안에 텍스트 영역을 가지고 있었습니다.이 텍스트 영역은 초점을 잃었습니다.버그가 많은 포털의 실장은 다음과 같습니다.

export const Modal = ({children, onClose}: modelProps) => {
  const modalDOM = document.getElementById("modal");
  const divRef = useRef(document.createElement('div')); 

  useEffect(()=>{
    const ref = divRef.current;
    modalDOM?.appendChild(ref);
    return ()=>{
      modalDOM?.removeChild(ref);
    }
  });

  const close = (e: React.MouseEvent) => {
    e.stopPropagation();
    onClose();
  };

  const handleClick = (e: React.MouseEvent) => {
    e.stopPropagation()
  }

  return (
    createPortal(
    <div className="modal" onClick={close}>
      <div className="modal__close-modal" onClick={close}>x</div>
      {children}
    </div>, 
    divRef.current)
  )
}

const Parent = ({content: string}: ParentProps) => {
  const [content, setContent] = useState<string>(content);
  
  const onChangeFile = (e: React.MouseEvent) => {
    setContent(e.currentTarget.value);
  }

  return (
    <Modal>
      <textarea
        value={content}
        onChange={onChangeFile}>
      </textarea>
    </Modal>
    )
  }

실장 후 정상적으로 동작한 것으로 판명되었습니다.여기서는 DOM 요소에 직접 modal component를 부가합니다.

export const Modal = ({children, onClose}: modelProps) => {
  const modalDOM = document.getElementById("modal");

  const close = (e: React.MouseEvent) => {
    e.stopPropagation();
    onClose();
  };

  return (
    createPortal(
      <div className="modal" onClick={close}>
        <div className="modal__close-modal" onClick={close}>x</div>
          {children}
        </div>, 
        modalDOM || document.body)
    )
  }

보니 내가 바인딩하고 .this이치노

혹시 다른 사람이 이런 문제가 생길까 봐 여기에 올려야겠다고 생각했어요

난 바꿔야 했다.

<Field
    label="Post Content"
    name="text"
    component={this.renderField.bind(this)}
/>

로.

<Field
    label="Post Content"
    name="text"
    component={this.renderField}
/>

에는 사실 때문에 입니다.thisrenderField하지만 제가 이 글을 올리면 다른 사람에게 도움이 될 거예요.

일부 컨트롤 입력의 텍스트를 변경하면 부모 컨트롤이 (소품과의 바인딩에 따라) 재렌더링될 수 있습니다.이 경우 포커스가 손실됩니다.편집은 DOM의 상위 컨테이너에 영향을 주지 않아야 합니다.

언급URL : https://stackoverflow.com/questions/22573494/react-js-input-losing-focus-when-rerendering