programing

ReactJs: 여러 번 버튼 누름 방지

megabox 2023. 3. 15. 19:30
반응형

ReactJs: 여러 번 버튼 누름 방지

리액트 컴포넌트에는 클릭 시 AJAX를 통해 데이터를 전송하는 버튼이 있습니다.처음 사용 후 버튼을 비활성화해야 하는 경우 등 처음만 수행해야 합니다.

이 작업을 수행하는 방법:

var UploadArea = React.createClass({

  getInitialState() {
    return {
      showUploadButton: true
    };
  },

  disableUploadButton(callback) {
    this.setState({ showUploadButton: false }, callback);
  },

  // This was simpler before I started trying everything I could think of
  onClickUploadFile() {
    if (!this.state.showUploadButton) {
      return;
    }
    this.disableUploadButton(function() {
      $.ajax({
        [...]
      });

    });
  },

  render() {
    var uploadButton;
    if (this.state.showUploadButton) {
      uploadButton = (
        <button onClick={this.onClickUploadFile}>Send</button>
      );
    }

    return (
      <div>
        {uploadButton}
      </div>
    );
  }

});

제가 생각하는 것은 상태 변수입니다.showUploadButton리액트 문서에서는 예상된 대로 즉시 업데이트되지 않습니다.

버튼을 클릭하는 순간 버튼을 강제로 비활성화하거나 완전히 해제하려면 어떻게 해야 합니까?

해결 방법은 핸들러에 들어가는 즉시 상태를 확인하는 것입니다.React는 브라우저 이벤트 경계에서 인터랙티브이벤트(클릭 등) 내의 setState가 플러시됨을 보증합니다.참고 자료: https://github.com/facebook/react/issues/11171#issuecomment-357945371

// In constructor
this.state = {
    disabled : false
};


// Handler for on click
handleClick = (event) => {
    if (this.state.disabled) {
        return;
    }
    this.setState({disabled: true});
    // Send     
}

// In render
<button onClick={this.handleClick} disabled={this.state.disabled} ...>
    {this.state.disabled ? 'Sending...' : 'Send'}
<button>

버튼을 클릭한 후 비활성화하여 페이지에 그대로 둡니다(클릭할 수 없는 요소).

이를 위해서는 버튼 요소에 참조를 추가해야 합니다.

<button ref="btn" onClick={this.onClickUploadFile}>Send</button>

그런 다음 onClickUploadFile 함수로 버튼을 비활성화합니다.

this.refs.btn.setAttribute("disabled", "disabled");

그런 다음 비활성화된 버튼을 적절하게 스타일링하여 사용자에게 다음과 같은 피드백을 제공할 수 있습니다.

.btn:disabled{ /* styles go here */}

필요에 따라서, 반드시 다음의 방법으로 재차 유효하게 해 주세요.

this.refs.btn.removeAttribute("disabled");

업데이트: React에서 참조를 처리하는 데 선호되는 방법은 문자열이 아닌 함수를 사용하는 것입니다.

<button 
  ref={btn => { this.btn = btn; }} 
  onClick={this.onClickUploadFile}
>Send</button>


this.btn.setAttribute("disabled", "disabled");
this.btn.removeAttribute("disabled");

업데이트: 리액트 훅 사용

import {useRef} from 'react';
let btnRef = useRef();

const onBtnClick = e => {
  if(btnRef.current){
    btnRef.current.setAttribute("disabled", "disabled");
  }
}

<button ref={btnRef} onClick={onBtnClick}>Send</button>

https://jsfiddle.net/69z2wepo/30824/ 에서 입력한 코드를 사용한 작은 예를 다음에 나타냅니다.

동작 테스트 완료:http://codepen.io/zvona/pen/KVbVPQ

class UploadArea extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      isButtonDisabled: false
    }
  }

  uploadFile() {
    // first set the isButtonDisabled to true
    this.setState({
      isButtonDisabled: true
    });
    // then do your thing
  }

  render() {
    return (
      <button
        type='submit'
        onClick={() => this.uploadFile()}
        disabled={this.state.isButtonDisabled}>
        Upload
      </button>
    )
  }
}

ReactDOM.render(<UploadArea />, document.body);

리액트 훅을 사용하여 컴포넌트 상태를 설정할 수 있습니다.

import React, { useState } from 'react';

const Button = () => {
  const [double, setDouble] = useState(false);
  return (
    <button
      disabled={double}
      onClick={() => {
        // doSomething();
        setDouble(true);
      }}
    />
  );
};

export default Button;

사용하고 있는 것을 확인해 주세요.^16.7.0-alpha.x버전 또는 그 이후react그리고.react-dom.

도움이 되시길 바랍니다!

원하시면 제출을 막으시면 됩니다.

를 사용하는 것은 어떻습니까?lodash.js debounce

갑작스러운 이벤트(키 입력 등)를 1개의 이벤트로 그룹화합니다.

https://lodash.com/docs/4.17.11#debounce

<Button accessible={true}
    onPress={_.debounce(async () => {
                await this.props._selectUserTickets(this.props._accountId)
    }, 1000)}
></Button>

onClick 중에 버튼을 비활성화하면 기본적으로 이 메시지가 나타납니다.이를 위한 깔끔한 방법은 다음과 같습니다.

import React, { useState } from 'react';
import Button from '@material-ui/core/Button';

export default function CalmButton(props) {
    const [executing, setExecuting] = useState(false);

    const {
        disabled,
        onClick,
        ...otherProps
    } = props;

    const onRealClick = async (event) => {
        setExecuting(true);
        try {
            await onClick();
        } finally {
            setExecuting(false);
        }
    };

    return (
        <Button
            onClick={onRealClick}
            disabled={executing || disabled}
            {...otherProps}
        />
    )
}

자세한 것은, https://codesandbox.io/s/extended-button-that-disabled-itself-during-onclick-execution-mg6z8 를 참조해 주세요.

기본적으로 Button 구성 요소를 확장하여 onClick 실행 시 비활성화되는 추가 동작을 수행합니다.이를 위한 절차:

  1. 실행 중인 경우 캡처할 로컬 상태 생성
  2. 조작한 속성 추출(비활성화, onClick)
  3. 실행 상태 설정을 포함한 클릭 작업 확장
  4. 덮어쓰기 onClick 및 확장 비활성화 상태에서 버튼을 렌더링합니다.

메모: 원래 onClick 조작이 비동기인지, 즉 Promise를 반환하고 있는지 확인해야 합니다.

「」를 사용해 .event.target이치노 함수를 을 사용합니다.onClick이벤트를 파라미터로 전달하는 것을 잊지 마십시오.

코드 보기펜

코드는 다음과 같습니다.

class Buttons extends React.Component{
  constructor(props){
    super(props)
    this.buttons = ['A','B','C','D']
  }

  disableOnclick = (e) =>{
    e.target.disabled = true
  }

  render(){
    return(

     <div>
        {this.buttons.map((btn,index) => (
          <button type='button' 
            key={index} 
            onClick={(e)=>this.disableOnclick(e)}
            >{btn}</button>
        ))}
      </div>
  )}

}
ReactDOM.render(<Buttons />, document.body);
const once = (f, g) => {
    let done = false;
    return (...args) => {
        if (!done) {
            done = true;
            f(...args);
        } else {
            g(...args);
        }
    };
};

const exampleMethod = () => console.log("exampleMethod executed for the first time");
const errorMethod = () => console.log("exampleMethod can be executed only once")

let onlyOnce = once(exampleMethod, errorMethod);
onlyOnce();
onlyOnce();

산출량

exampleMethod executed for the first time
exampleMethod can be executed only once

및 onClick 수 있습니다.setAttribute예를 들어 다음과 같습니다.

      <Button
        onClick={(e) => {
          e.target.setAttribute("disabled", true);
          this.handler();
        }}            
      >
        Submit
      </Button>

심플하고 인라인으로 유지:

<button type="submit"
        onClick={event => event.currentTarget.disabled = true}>
    save
</button>

단! 양식 확인에 실패하면 버튼도 비활성화됩니다!그래서 당신은 다시 제출할 수 없습니다.

이 경우 세터가 더 좋습니다.

, 「비활성화」, 「」로 됩니다.onSubmit의의: :


// state variable if the form is currently submitting
const [submitting, setSubmitting] = useState(false);

// ...
return (
<form onSubmit={e => {
                setSubmitting(true); // create a method to modify the element
            }}>

    <SubmitButton showLoading={submitting}>save</SubmitButton>
</form>
);

버튼은 다음과 같습니다.

import {ReactComponent as IconCog} from '../../img/icon/cog.svg';
import {useEffect, useRef} from "react";

export const SubmitButton = ({children, showLoading}) => {

    const submitButton = useRef();

    useEffect(() => {
        if (showLoading) {
            submitButton.current.disabled = true;
        } else {
            submitButton.current.removeAttribute("disabled");
        }
    }, [showLoading]);

    return (
        <button type="submit"
                ref={submitButton}>
            <main>
                <span>{children}</span>
            </main>
        </button>
    );

};

또 다른 접근방식은 다음과 같습니다.

<button onClick={this.handleClick} disabled={isLoading ? "disabled" :""}>Send</button>

제 접근법은 처리 중인 이벤트가 아무것도 실행되지 않는 경우입니다.

class UploadArea extends React.Component {
constructor(props) {
super(props)

this.state = {
  onProcess:false
   }
}

uploadFile() {
 if (!this.state.onProcess){
   this.setState({
     onProcess: true
   });
   // then do your thing
   this.setState({
     onProcess: false;
   });
 }    
}

render() {
  return (
    <button
      type='submit'
      onClick={() => this.uploadFile()}>
      Upload
    </button>
   )
  }
}

ReactDOM.render(<UploadArea />, document.body);

다음 코드를 사용하여 시도합니다.

class Form extends React.Component {
    constructor() {
        this.state = {
            disabled: false,
        };
    }

    handleClick() {
        this.setState({
            disabled: true,
        });

        if (this.state.disabled) {
            return;
        }

        setTimeout(() => this.setState({ disabled: false }), 2000);
    }

    render() {
        return (
            <button type="submit" onClick={() => this.handleClick()} disabled={this.state.disabled}>
                Submit
            </button>
        );
    }
}

ReactDOM.render(<Form />, document.getElementById('root'));

언급URL : https://stackoverflow.com/questions/35315872/reactjs-prevent-multiple-times-button-press

반응형