React/기타

[React]Warning: A component is changing an uncontrolled input to be controlled.

DevStory 2021. 7. 22.

경고

『 A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. 』

 

해석

'컴포넌트는 제어할수없는 input을 제어하기 위해 변경하고 있습니다.

해당 경고는 undefined에서 정의된 값으로 변경할려고 해서 발생하였으며, 이러한 경우는 발생해서는 안됩니다.

컴포넌트의 일생동안 input element가 제어가 가능한지 제어가 불가능한지 결정해야합니다.'


경고 원인

위 해석을 간단하게 정리하면, 활성화 되어 있는 컴포넌트에서 input elementvalue 초기 값으로 undefined가 들어가서 문제가 발생하였습니다.

value 초기 값을 설정하지 않으면, input element는 제어되지 않은 구성 요소로 처리됩니다.

<input
  type="text"
  value={this.state.list.Author} // this.state.list.Author이 undefined라서 경고가 발생함.
  onChange={this.handleOnChange}
/>

경고 해결

null/undefined 을 확인하는 코드를 추가합니다.

<input
  type="text"
  value={this.state.list.Author || ''}
  onChange={this.handleOnChange}
/>

TS 또는 Babel을 사용하는 경우 nulish 병합을 사용할 수 있습니다.

<input
  type="text"
  value={this.state.list.Author ?? ''}
  onChange={this.handleOnChange}
/>

uncontrolled Element vs controlled Element

제어가 불가능한 Element와 제어가 가능한 Element가 무엇이길래 경고가 발생했는지 궁금하여 정리하였습니다.

 

제어가 불가능한 Element와 제어가 가능한 Element의 차이점은 현재 값(value)이 저장되는 위치입니다.

제어가 불가능한 Element의 값(value)은 DOMHTML 입력 내부에 저장됩니다.

제어가 가능한 Element의 값(value)은 React 컴포넌트 내부에 저장됩니다.

 

제어가 불가능한 Element

class Test extends React.Component {
  render() {
    return (
      <div>
        <form>
          <div>
            <label>Input: </label>
            <input type="text" onChange={(e) => console.log(e.target.value)} />
          </div>
        </form>
      </div>
    );
  }
}

제어가 가능한 Element

state의 초기값으로 input Element의 값을 설정하고 state가 변경될 때마다 변경된 state의 값을 input Element의 값에 설정합니다.

class Test extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      term: ""
    };
  }

  render() {
    return (
      <div>
        <form>
          <div>
            <label>Input: </label>
            <input type="text" onChange={(e) => console.log(e.target.value)} />
          </div>
        </form>
      </div>
    );
  }
}

 

반응형

댓글