Я использую альфа-версию реакционных поддерживающих хуков и хочу проверить мой подход к обновлению текста в компоненте после интервала без рендеринга компонента больше раз, чем необходимо при изменении пропа.
РЕДАКТИРОВАТЬ : для ясности - этот компонент вызывает moment(timepoint).fromNow()
в функции formatTimeString
( документы здесь ), поэтому обновление несовершенно ненужно, я обещаю!
У меня ранее было:
const FromNowString = ({ timePoint, ...rest }) => {
const [text, setText] = useState(formatTimeString(timePoint));
useEffect(() => {
setText(formatTimeString(timePoint));
let updateInterval = setInterval(
() => setText(formatTimeString(timePoint)),
30000
);
return () => {
clearInterval(updateInterval);
};
}, [timePoint]);
// Note the console log here is so we can see when renders occur
return (
<StyledText tagName="span" {...rest}>
{console.log('render') || text}
</StyledText>
);
};
Это «работает» - компонент корректно обновляется, если изменяется реквизит, и компонент обновляется через каждый интервал, однако при монтировании и при изменении реквизита компонент будет визуализироваться дважды.
Это связано с тем, что useEffect
запускает после визуализации, которая возникает при изменении значения timePoint
, ивнутри моего useEffect
обратного вызова я немедленно вызываю setState
метод, который запускает дополнительный рендеринг.
Очевидно, что если я удалю этот вызов к setText
, компонент не изменится, когда пропизменения (до тех пор, пока не закончится интервал), потому что text
остается прежним.
Я наконец-то понял, что могу запустить рендеринг, установив переменную состояния, которая мне на самом деле не нужна, например:
const FromNowString = ({ timePoint, ...rest }) => {
// We never actually use this state value
const [, triggerRender] = useState(null);
useEffect(() => {
let updateInterval = setInterval(() => triggerRender(), 30000);
return () => {
clearInterval(updateInterval);
};
}, [timePoint]);
return (
<StyledText tagName="span" {...rest}>
{console.log("render") || formatTimeString(timePoint)}
</StyledText>
);
};
Это работает отлично, компонент рендерит только один раз, когда он монтируется, и один раз, когда меняется пропеллер timePoint
, но он чувствует себя хакером.Это правильный путь, или я что-то упускаю?