Мой счетчик React Simple не работает должным образом

Я начинаю изучать React, и мне было интересно, почему мой счетчик не работает :( Моя цель: когда вы нажимаете кнопку, функция счетчика начинает «подсчитывать» и отображать состояние «подсчет» в td. Я не знаю, что я делаю неправильно.

import React, { useState } from "react";


function Clock() {
  const customStyle = {
    fontSize: "100px"
  };
  const tdStyle = "px-3 border border-dark border-3 rounded bg-secondary";
  //-------------------------------------------------------------------------
// THIS FUNCTION 
  const [count, setCount] = useState(0);

  function Counter(){
    setCount(count + 1)
    setInterval(Counter, 1000)
  }  
 

  return (
    <div className="rounded border border-dark border-3">
      <table>
        <tr style={customStyle}>
          <td className={tdStyle}>
            <i className="fa-solid fa-clock"></i>
          </td>
          <td className={tdStyle}>0</td>
          <td className={tdStyle}>0</td>
          <td className={tdStyle}>0</td>
          <td className={tdStyle}>0</td>
          <td className={tdStyle}>0</td>
          <td className={tdStyle}>{count}</td>    //here is showed
        </tr>
      </table>
      <button onClick={Counter}>Pulsar</button>    //button
    </div>
  );
}

export default Clock;

Это работает с реальными секундами

function Counter(){
    setCount(new Date().getSeconds())
    setInterval(Counter, 1000)
  }

Но это не то, чего я хочу. Мне нужен простой счетчик.

Кроме того, как я могу использовать событие onLoad в этом коде? когда страница загружается, она начинает считать и отображать ее на странице?

Заранее спасибо!!

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Сравнение структур данных: Массивы и объекты в Javascript
Сравнение структур данных: Массивы и объекты в Javascript
Итак, вы изучили основы JavaScript и хотите перейти к изучению структур данных. Мотивация для изучения/понимания Структур данных может быть разной,...
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Прошлая статья была первой из цикла статей о создании системы электронной коммерции с использованием Keystone.js, и она была посвящена главным образом...
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
Стоит ли использовать React в 2022 году?
Стоит ли использовать React в 2022 году?
В 2022 году мы все слышим о трендах фронтенда (React, Vue), но мы не знаем, почему мы должны использовать эти фреймворки, когда их использовать, а...
1
0
37
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если я понимаю, как правильно работает useState, я полагаю, что вы сталкиваетесь с некоторыми асинхронными проблемами с вашим состоянием подсчета, что объясняет, почему работает ваш пример «реальных секунд».

Я бы предложил перенести вашу функцию setInterval() на крючок useEffect. Крючок useEffect также будет ответом на ваш вопрос onLoad.

import React, { useState, useEffect } from "react";


function Clock() {
  const customStyle = {
    fontSize: "100px"
  };
  const tdStyle = "px-3 border border-dark border-3 rounded bg-secondary";
  //-------------------------------------------------------------------------
// THIS FUNCTION 
  const [count, setCount] = useState(0);

useEffect(() => {
  setInterval(counter, 1000);
}, []);

  function Counter(){
    setCount(count + 1)
  }  
 

  return (
    <div className="rounded border border-dark border-3">
      <table>
        <tr style={customStyle}>
          <td className={tdStyle}>
            <i className="fa-solid fa-clock"></i>
          </td>
          <td className={tdStyle}>0</td>
          <td className={tdStyle}>0</td>
          <td className={tdStyle}>0</td>
          <td className={tdStyle}>0</td>
          <td className={tdStyle}>0</td>
          <td className={tdStyle}>{count}</td>    //here is showed
        </tr>
      </table>
      <button onClick={Counter}>Pulsar</button>    //button
    </div>
  );
}

export default Clock;

Я не на 100% уверен, что это будет работать так, как ожидалось, поскольку я не могу проверить это в данный момент, но я считаю, что это то, что вы ищете. Вот документация по useEffect, https://reactjs.org/docs/hooks-effect.html

Боюсь, что это не работает для меня :(. Ничего не происходит, я скопировал ваш пример

Karim 17.05.2022 19:02
Counter — это замыкание, поэтому в нем не будет использоваться обновленная версия переменной count, поэтому этот ответ не сработает.
Ben 17.05.2022 19:14
Ответ принят как подходящий

Во-первых, вам нужно поместить свой setInterval в хук useEffect, потому что в настоящее время вы создаете новый интервал каждый раз, когда ваше состояние обновляется (т.е. каждую секунду), что резко замедлит ваше приложение. Во-вторых, вы должны использовать функцию очистки useEffect, чтобы удалять интервал каждый раз, когда ваш компонент выполняет повторную визуализацию, чтобы предотвратить создание повторяющихся интервалов. Наконец, учитывая, что ваше состояние зависит от предыдущего снимка состояния (т. е. от предыдущего значения счетчика), вам следует обновить свое состояние с помощью обратного вызова (чтобы обеспечить доступ к самому последнему снимку состояния).

useEffect(() => {

  function counter(){
    setCount(prevState => prevState + 1)
  }

  let countInterval = setInterval(counter, 1000)

  return () => clearInterval(countInterval)

}, [])

Учитывая, что вы вызываете useEffect каждый раз, когда обновляется счетчик, вы можете (и, вероятно, должны) использовать setTimeout вместо setInterval. В этом случае вам не потребуется функция очистки.

Ага! Это работает отлично. Спасибо большое, постараюсь разобраться в этом лучше!

Karim 17.05.2022 19:21

Пожалуйста! Определенно стоит посмотреть, как обновляется состояние React (т. е. асинхронно) и проверить хук useEffect (это будет решением многих ваших проблем, поскольку он предотвращает запуск кода каждый раз, когда компонент перерисовывается).

Ben 17.05.2022 19:24

Вы уверены, что хотите count в списке зависимостей?

Ben Stephens 17.05.2022 20:32

@BenStephens Ты прав; мой ответ изначально использовал count в функции useEffect (таким образом, это было необходимо, чтобы переменная не была устаревшим закрытием). Приведенный выше код по-прежнему будет работать, но useEffect будет выполняться без необходимости, поэтому я его отредактирую.

Ben 18.05.2022 00:51

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