Не удается прочитать свойство "innerHTML" из null

Попытка создать простой текстовый эффект в моем классе «О программе». Я делаю это с помощью React. Он продолжает говорить мне, что не может прочитать свойство innerHTML.

Я думаю, что он не может видеть элемент в рендере и поэтому считает его нулевым. Как это исправить?

class About extends Component
{
  constructor(props){
    super(props)
    this.loading = this.loading.bind(this)
  }

  loading() {
    console.info('i got here')
    let i = 0;
    let txt = this.props.text;
    let speed = 50;
    function typeWriter() {
      if ( i < txt.length){
        document.getElementById("welcome").innerHTML += txt.charAt(i);
        i++;
        setTimeout(typeWriter,speed);
      }
    }
    typeWriter()
  }


    render()
    {
        return(
            <div className = "about">
            <h1 id = "welcome" onload = {this.loading()}></h1>
            <p>some text</p>
            </div>
        );
    }
}

Я просто хочу изменить текст в приветствии, чтобы отображать символ за символом, что-то вроде эффекта набора текста.

Опечатка: this.loading() добавлено (). Удалите это. Назначьте функцию. Не вызывайте его и не присваивайте возвращаемое значение.

Quentin 10.05.2019 17:13

Вы должны использовать setState() вместо прямого управления DOM.

SLaks 10.05.2019 17:15

вы вызываете метод loading в методе render, имейте в виду, что на данный момент реакция не отобразила эти элементы в dom, поэтому document.getElementById('welcome') будет нулевым, вам следует рассмотреть возможность использования setState, если вы действительно хотите манипулировать dom вручную, вы должны заменить onload = {this.loading()} на onload = {this.loading}

Olivier Boissé 10.05.2019 18:07
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
96
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы должны использовать либо состояние, либо ссылки. А затем запустите свою функцию на componentDidMount вместо использования функции onload. Таким образом, с рефами это будет выглядеть примерно так:

class About extends Component {
  constructor(props) {
    super(props);
    this.loading = this.loading.bind(this);
    this.elRef = React.createRef();
  }

  componentDidMount() {
    this.loading();
  }

  loading() {
    const el = this.elRef.current;
    let i = 0;
    let txt = 'Hello';
    let speed = 50;
    function typeWriter() {
      if (i < txt.length) {
        el.innerHTML += txt.charAt(i);
        i++;
        setTimeout(typeWriter, speed);
      }
    }
    typeWriter();
  }

  render() {
    return (
      <div className = "about">
        <h1 ref = {this.elRef} />
        <p>some text</p>
      </div>
    );
  }
}

Манипулирование домом немного сложнее с реагированием, так как оно использует виртуальный DOM. Поэтому, когда вы пытаетесь манипулировать им, большую часть времени элемент еще не был отображен в фактическом DOM. Поэтому при манипулировании элементом DOM вам нужно использовать реагирующие ссылки Реагировать на ссылки или вы можете установить свои значения в состояние. Но в вашем случае это будет вызывать повторную визуализацию каждый раз, когда появляется письмо, поэтому refs, вероятно, будет лучшим выбором для вашего случая.

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