Я начинаю изучать 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 в этом коде? когда страница загружается, она начинает считать и отображать ее на странице?
Заранее спасибо!!
Если я понимаю, как правильно работает 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
Counter
— это замыкание, поэтому в нем не будет использоваться обновленная версия переменной count
, поэтому этот ответ не сработает.
Во-первых, вам нужно поместить свой setInterval в хук useEffect, потому что в настоящее время вы создаете новый интервал каждый раз, когда ваше состояние обновляется (т.е. каждую секунду), что резко замедлит ваше приложение. Во-вторых, вы должны использовать функцию очистки useEffect, чтобы удалять интервал каждый раз, когда ваш компонент выполняет повторную визуализацию, чтобы предотвратить создание повторяющихся интервалов. Наконец, учитывая, что ваше состояние зависит от предыдущего снимка состояния (т. е. от предыдущего значения счетчика), вам следует обновить свое состояние с помощью обратного вызова (чтобы обеспечить доступ к самому последнему снимку состояния).
useEffect(() => {
function counter(){
setCount(prevState => prevState + 1)
}
let countInterval = setInterval(counter, 1000)
return () => clearInterval(countInterval)
}, [])
Учитывая, что вы вызываете useEffect каждый раз, когда обновляется счетчик, вы можете (и, вероятно, должны) использовать setTimeout
вместо setInterval
. В этом случае вам не потребуется функция очистки.
Ага! Это работает отлично. Спасибо большое, постараюсь разобраться в этом лучше!
Пожалуйста! Определенно стоит посмотреть, как обновляется состояние React (т. е. асинхронно) и проверить хук useEffect (это будет решением многих ваших проблем, поскольку он предотвращает запуск кода каждый раз, когда компонент перерисовывается).
Вы уверены, что хотите count
в списке зависимостей?
@BenStephens Ты прав; мой ответ изначально использовал count
в функции useEffect (таким образом, это было необходимо, чтобы переменная не была устаревшим закрытием). Приведенный выше код по-прежнему будет работать, но useEffect будет выполняться без необходимости, поэтому я его отредактирую.
Боюсь, что это не работает для меня :(. Ничего не происходит, я скопировал ваш пример