React.js에서 버튼을 비활성화하는 방법


84

이 구성 요소가 있습니다.

import React from 'react';

export default class AddItem extends React.Component {

add() {
    this.props.onButtonClick(this.input.value);
    this.input.value = '';
}


render() {
    return (
        <div className="add-item">
            <input type="text" className="add-item__input" ref={(input) => this.input = input} placeholder={this.props.placeholder} />
            <button disabled={!this.input.value} className="add-item__button" onClick={this.add.bind(this)}>Add</button>
        </div>
    );
}

}

입력 값이 비어있을 때 버튼을 비활성화하고 싶습니다. 그러나 위의 코드는 작동하지 않습니다. 그것은 말한다 :

add-item.component.js : 78 Uncaught TypeError : Cannot read property 'value'of undefined

가리키는 disabled={!this.input.value}. 여기서 내가 뭘 잘못하고 있니? render메서드가 실행될 때 아마도 ref가 아직 생성되지 않았다고 생각합니다 . 그렇다면 해결 방법은 무엇입니까?

답변:


109

refsDOM을 직접 읽으므로 사용 은 모범 사례가 아니며 state대신 React를 사용하는 것이 좋습니다. 또한 구성 요소가 다시 렌더링되지 않고 초기 상태를 유지하므로 버튼이 변경되지 않습니다.

이벤트 리스너 setState와 함께 사용 onChange하여 입력 필드가 변경 될 때마다 구성 요소를 다시 렌더링 할 수 있습니다 .

// Input field listens to change, updates React's state and re-renders the component.
<input onChange={e => this.setState({ value: e.target.value })} value={this.state.value} />

// Button is disabled when input state is empty.
<button disabled={!this.state.value} />

다음은 작동하는 예입니다.

class AddItem extends React.Component {
  constructor() {
    super();
    this.state = { value: '' };
    this.onChange = this.onChange.bind(this);
    this.add = this.add.bind(this);
  }

  add() {
    this.props.onButtonClick(this.state.value);
    this.setState({ value: '' });
  }

  onChange(e) {
    this.setState({ value: e.target.value });
  }

  render() {
    return (
      <div className="add-item">
        <input
          type="text"
          className="add-item__input"
          value={this.state.value}
          onChange={this.onChange}
          placeholder={this.props.placeholder}
        />
        <button
          disabled={!this.state.value}
          className="add-item__button"
          onClick={this.add}
        >
          Add
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <AddItem placeholder="Value" onButtonClick={v => console.log(v)} />,
  document.getElementById('View')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='View'></div>


이것은 정답입니다! 내부 상태는 입력 변경시 업데이트하는 데 사용되어야하며 버튼은이를 확인해야합니다. +1
Michael Giovanni Pumo

this.state는 UI를 다시 렌더링하는 제한이 있으므로 하위 구성 요소의 텍스트 상자에 입력하고 onChange 이벤트에 바인딩 된 경우 텍스트 상자에서 포커스를 잃게됩니다. 동일한 구성 요소에 있으면 괜찮지 만 자식 구성 요소에서 사용하면 포커스를 잃습니다.
Dynamic

@Dynamic 그렇게해서는 안됩니다. 작동하는 예가 있습니까?
Fabian Schultz

참고로 이것은 브라우저 간 친화적이지 않습니다. 대부분의 브라우저는 false로 설정되어 있어도 비활성화 상태를 true로 해석합니다. 말 그대로 비활성화 된 속성의 존재를 확인하는 것처럼. 브라우저 간 친화적이려면 disabled 속성을 제거해야합니다.
Adrianopolis

@Adrianopolis React는 disabledDOM 에서 속성을 제거합니다.이 속성은 false브라우저 간 친화적입니다.
Fabian Schultz

9

HTML에서

<button disabled/>
<buttton disabled="true">
<buttton disabled="false">
<buttton disabled="21">

비어 있지 않은 문자열에 대해 true를 반환하기 때문에 모두 disabled = "true"로 요약됩니다. 따라서 false를 반환하려면 this.input.value? "true": "" 와 같은 조건문에 빈 문자열을 전달합니다 .

render() {
    return (
        <div className="add-item">
            <input type="text" className="add-item__input" ref={(input) => this.input = input} placeholder={this.props.placeholder} />
            <button disabled={this.input.value?"true":""} className="add-item__button" onClick={this.add.bind(this)}>Add</button>
        </div>
    );
}

스택 오버플로에 지원 답변 옵션이있는 경우이 답변을 선택합니다
Feras

6

refs를 통해 입력 값을 설정해서는 안됩니다.

https://facebook.github.io/react/docs/forms.html#control-components 에서 제어 된 양식 구성 요소에 대한 설명서를 살펴보십시오.

간단히 말해서

<input value={this.state.value} onChange={(e) => this.setState({value: e.target.value})} />

그런 다음 사용하여 비활성화 상태를 제어 할 수 있습니다. disabled={!this.state.value}


4

React에서 컴포넌트 렌더링을 제어하는 ​​일반적인 방법은 거의 없습니다. 여기에 이미지 설명 입력

그러나 나는 여기에서 이것들 중 어느 것도 사용하지 않았으며, 단지 참조를 사용하여 구성 요소의 기본 자식을 네임 스페이스로 지정했습니다.

class AddItem extends React.Component {
    change(e) {
      if ("" != e.target.value) {
        this.button.disabled = false;
      } else {
        this.button.disabled = true;
      }
    }

    add(e) {
      console.log(this.input.value);
      this.input.value = '';
      this.button.disabled = true;
    }

    render() {
        return (
          <div className="add-item">
          <input type="text" className = "add-item__input" ref = {(input) => this.input=input} onChange = {this.change.bind(this)} />
          
          <button className="add-item__button" 
          onClick= {this.add.bind(this)} 
          ref={(button) => this.button=button}>Add
          </button>
          </div>
        );
    }
}

ReactDOM.render(<AddItem / > , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>


2

this.inputref콜백이 호출 될 때까지 정의되지 않습니다 . this.input생성자에서 초기 값을 설정해보십시오 .

에서 (가) 심판에 문서 반응 강조 광산 :

콜백 즉시 실행될 부품 장착 또는 IS 마운트


0

비슷한 문제가 있었는데이를 수행하기 위해 후크가 필요하지 않다는 것이 밝혀졌습니다. 조건부 렌더링을 만들 수 있으며 여전히 잘 작동합니다.

<Button
    type="submit"
    disabled={
        name === "" || email === "" || password === "" ? true : false
    }
    fullWidth
    variant="contained"
    color="primary"
    className={classes.submit}>
    SignUP
</Button>

0

그냥 추가 :

<button disabled={this.input.value?"true":""} className="add-item__button" onClick={this.add.bind(this)}>Add</button>

0

이것에 대한 매우 간단한 해결책은 useRef후크 를 사용하는 것입니다.

const buttonRef = useRef();

const disableButton = () =>{
  buttonRef.current.disabled = true; // this disables the button
 }

<button
className="btn btn-primary mt-2"
ref={buttonRef}
onClick={disableButton}
>
    Add
</button>

마찬가지로 다음을 사용하여 버튼을 활성화 할 수 있습니다. buttonRef.current.disabled = false

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.