ReactJs компонент пользовательской кнопки отправки не работает - PullRequest
0 голосов
/ 28 апреля 2020

Я пытаюсь создать пользовательский компонент кнопки отправки, который будет обрабатывать отключение и включение кнопки самостоятельно. До сих пор я получил это:

Компонент кнопки:

import * as React from 'react';
import Promise = require('promise');

let isDisabled = false;

const buttonClickHandler = onClick => {
  return new Promise((resolve, reject) => {
    console.log('inside promise');
    isDisabled = true;
    onClick();
    return resolve(true);
  });
};

export const SubmitButton = ({
  type,
  className,
  onClick,
  buttonStyle = {},
  children
}) => {
  return (
    <button
      type={type || 'submit'}
      className={className}
      onClick={() =>
        buttonClickHandler(onClick).then(() => {
          console.log('after promise');
          isDisabled = false;
        })
      }
      style={buttonStyle}
      disabled={isDisabled}
    >
      {children}
    </button>
  );
};

export default SubmitButton;

Я вызываю это так:

<SubmitButton type="button" className="btn btn-primary" onClick={this.submitForm}>
Submit
</SubmitButton>

Функция отправки формы:

public submitForm = () => {
  setTimeout(() => {
    console.log('waiting done');
  }, 5000);
};

Таким образом, ожидаемый результат равен

inside promise
---- ожидание 5000 мс ----
waiting done
after promise

но я вижу
inside promise
after promise
---- подождите 5000 мс ----
waiting done

Так что же я сделал неправильно? Также кнопка не отключается.

Ответы [ 3 ]

1 голос
/ 28 апреля 2020

Немного исправлений:

  • isDisabled должен быть состоянием, а не глобальной переменной
  • переместить функцию buttonClickHandler в компоненте SubmitButton
  • onClick() внутри компонента SubmmitButton необходимо вернуть обещание

рабочая копия вашего кода находится здесь

export const SubmitButton = ({
  type,
  className,
  onClick,
  buttonStyle = {},
  children
}) => {
  const [isDisabled, setIsDisabled] = useState(false);
  const buttonClickHandler = onClick => {
    // return new Promise((resolve, reject) => {
    console.log("inside promise");
    setIsDisabled(true);
    return onClick();
    // });
  };
  return (
    <button
      type={type || "submit"}
      className={className}
      onClick={() =>
        buttonClickHandler(onClick).then(() => {
          console.log("after promise");
          setIsDisabled(false);
        })
      }
      style={buttonStyle}
      disabled={isDisabled}
    >
      {children}
    </button>
  );
};

export default SubmitButton;

Использование

const submitForm = () => {
    return new Promise((res, rej) => {
      setTimeout(() => {
        console.log("waiting done");
        res(true);
      }, 5000);
    });
  };
0 голосов
/ 28 апреля 2020

Basi c ответ на ваш подход заключается в том, что Javascript является асинхронным по своей природе.

Чтобы гарантировать, что выполнение происходит синхронно, мы используем Promises, как вы уже сделал в вашем текущем коде.

Вам просто нужно несколько настроек здесь.

Сначала вам нужно заставить свою функцию submitForm вернуть Promise

let submitForm = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('waiting done');
    }, 5000);
  })
};

А затем вам нужно убедиться, что submitForm завершает выполнение, прежде чем разрешить buttonClickHandler функцию

const buttonClickHandler = (onClick) => {
  return new Promise(async (resolve, reject) => {
    console.log('inside promise');
    isDisabled = true;
    onClick().then((res)=>{
      console.log(res)
      return resolve(true);
    });
  });
};

PS: код всегда можно реорганизовать

  • Избегайте использования зарезервированных ключевых слов, таких как onClick, в качестве имен пользовательских функций или переменных, это может привести к ошибкам.
  • Я рекомендую вам использовать state для управления loading.
0 голосов
/ 28 апреля 2020

Учитывая некоторый вызов базы данных, который разрешается через некоторое время в течение 10 секунд

const dbCall = () => {
  return new Promise((resolve, reject) => {
    console.log("inside promise, making DB call");
    setTimeout(resolve, Math.floor(Math.random() * 10000);
  });
};

И некоторый обработчик submitForm

const submitForm = () => {
  console.log("submitForm called");
  return dbCall();
};

Добавление состояния к кнопке и внутренний обработчик onClick управлять состоянием

const SubmitButton = ({
  type,
  className,
  onClick,
  buttonStyle = {},
  children
}) => {
  const [isDisabled, setIsDisabled] = useState();

  const clickHandler =  async () => {
    setIsDisabled(true);
    await onClick();
    console.log("after promise");
    setIsDisabled(false);
  }

  return (
    <button
      type={type || "submit"}
      className={className}
      onClick={clickHandler}
      style={buttonStyle}
      disabled={isDisabled}
    >
      {children}
    </button>
  );
};

Демо

Edit adoring-https-4psuu

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...