Индикатор загрузки при нажатии кнопки (reactjs и ant design)

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

Я старался

document.getElementById(inputID).setAttribute("загрузка", "истина");

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

document.getElementById("btnTesting").innerHTML = "ИЗВЛЕЧЕНО";

class DashboardPage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: false,
    }
  onClickBtn = () => {
    this.setState({ loading: true});
    document.getElementById("btnTesting").innerHTML = "EXTRACTED";
    document.getElementById("btnTesting").setAttribute("disabled","true");
  }
    render() {
       return (
          <Button id = "btnTesting" onClick = {this.onClickBtn} loading = {this.state.loading}>EXTRACT</Button>
       )
    }
  }

Я ожидаю, что при нажатии будет индикатор загрузки, а затем остановится, когда кнопка отключена. Но экран становится пустым. Я смотрю в консоль и вижу эту ошибку

Uncaught DOMException: не удалось выполнить «insertBefore» на «узле»: узел, перед которым должен быть вставлен новый узел, не является дочерним элементом этого узла.

Вышеупомянутая ошибка произошла в компоненте: бла . бла .

Uncaught DOMException: не удалось выполнить «insertBefore» на «узле»: узел, перед которым должен быть вставлен новый узел, не является дочерним элементом этого узла.

Перво-наперво. Почему бы вам не обработать текст кнопки и атрибут disabled в состоянии?

PRogalla 09.07.2019 12:18

Когда я использовал состояние, другие мои кнопки тоже меняются. Итак, я попытался использовать innerHTML

Alexandria.Omega.Reid 10.07.2019 07:23

@ Алекс. Рид. Чтобы избежать этого, вам придется использовать отдельное значение состояния для всех кнопок.

Mobeen 10.07.2019 07:47
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
3
3 376
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Поскольку вы используете React, вам не нужно использовать innerHTML или setAttribute для изменения текста кнопки или состояния отключения.

Вы можете использовать переменные состояния buttonText, инициализированные значением «Извлечь» и isDisabled, инициализированные значением false, и вы можете изменить состояние после выполнения кнопки.

class DashboardPage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: false,
      buttonText: "EXTRACT",
      isDisabled: false
    };
  }
  onClickBtn = () => {
    this.setState({ loading: true });
    setTimeout(() => {
      this.setState({
        buttonText: "EXTRACTED",
        isDisabled: true,
        loading: false
      });
    }, 2000);
  };
  render() {
    return (
      <Button
        id = "btnTesting"
        onClick = {this.onClickBtn}
        loading = {this.state.loading}
        disabled = {this.state.isDisabled}
      >
        {this.state.buttonText}
      </Button>
    );
  }
}

Я добавил setTimeout 2000 мс, чтобы вы могли видеть индикатор загрузки.

Найдите демо здесь: https://codesandbox.io/s/antd-reproduction-template-l1d4r

а если у меня несколько кнопок? Как я могу использовать свой идентификатор кнопки? На самом деле у нас есть динамический идентификатор от API. Итак, наш идентификатор выглядит примерно так: id = {extractButton-${value.sectionID}${value.specimenID}${val‌​ue.requestID}}

Alexandria.Omega.Reid 10.07.2019 04:27

Затем ваше состояние может иметь объекты для каждого идентификатора кнопки с текстом кнопки, состоянием загрузки и отключенным состоянием. Я обновил свой кодыпесочница с несколькими кнопками

yay 10.07.2019 15:43

да Именно то, что мне было нужно. Я также попробую использовать динамические имена объектов. Спасибо за это!

Alexandria.Omega.Reid 11.07.2019 04:01

Можете ли вы проверить, решает ли приведенный ниже код вашу проблему? Я добавил таймер, чтобы продемонстрировать влияние времени, чтобы загрузка стала очевидной.

С ReactJS вам не нужно использовать setAttribute или innerHTML, поскольку ReactJS использует virtualDOM. Даже если вы их используете, это может привести к несогласованному состоянию DOM. В соответствии со стандартной практикой React вы должны обрабатывать свои требования (например, изменение DOM) с помощью переменных состояния.

class DashboardPage extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        loading: {"btn1": false},
        disabled: false,
        buttonText: 'Extract'
      }
    onClickBtn = (btnStr) => {
      let loadingCopy = Object.assign({},this.state.loading)
      loadingCopy[btnStr] = true
      this.setState({loading: loadingCopy})
      setInterval(() => {
        loadingCopy[btnStr] = false
        this.setState({ loading: loadingCopy, buttonText: 'Extracted', disabled: true });
        }, 3000);
    }
    render() {
       return (
          <ButtononClick = {() =>this.onClickBtn("btn1")} loading = {this.state.loading["btn1"]} disabled = {this.state.disabled}>{this.state.buttonText}</Button>
         )
    }
}

Кажется, я пробовал это за несколько недель до этого. Но что происходит, если у меня есть несколько кнопок, все они загружаются и меняют метку одновременно. Но это то, что мне было нужно. Я просто не знаю, что мне делать, если у меня есть несколько кнопок. PS: я новичок в Reactjs.

Alexandria.Omega.Reid 10.07.2019 03:57
<Button id = "btn1" onClick = {this.onClickBtn} loading = {this.state.loading} disabled = {this.state.disabled}>{this.state.buttonText}</Butt‌​on> <Button id = "btn2" onClick = {this.onClickBtn} loading = {this.state.loading} disabled = {this.state.disabled}>{this.state.buttonText}</Butt‌​on>
Alexandria.Omega.Reid 10.07.2019 04:03

В этом случае каждая кнопка должна использовать разные переменные состояния для загрузки и текста кнопки. Это может привести к путанице, поэтому вы можете использовать массивы для представления каждого загружаемого текста.

Mobeen 10.07.2019 04:50

не могли бы вы уточнить?

Alexandria.Omega.Reid 10.07.2019 05:16

Я обновил свой ответ (проверьте, как сейчас обновляется загрузка состояния), чтобы дать вам представление. Вам нужно будет сделать то же самое и для других двух состояний.

Mobeen 10.07.2019 05:24
import { Button } from 'antd';
import React from "react";

class SubmitButton extends React.Component {
state = {
    loadings: [],
};

enterLoading = index => {
    this.setState(({loadings}) => {
        const newLoadings = [...loadings];
        newLoadings[index] = true;

        return {
            loadings: newLoadings,
        };
    });
};

render() {
    const {loadings} = this.state;
    return (
        <>
            <Button type = "primary" htmlType = "submit" loading = {loadings[0]} onClick = {() => this.enterLoading(0)}>
                Submit
            </Button>
        </>
    );
}

Код: https://codesandbox.io/s/withered-framework-w5lmc?file=/src/App.js

Другие вопросы по теме