我在React Native应用程序中的许多组件都要求知道当前时间是每秒。这样,我可以显示更新的实时信息。
我创建了一个简单的功能来使用new Date()
设置状态,但是每当设置状态时,组件都会重新渲染,这很浪费我的情况。
这是我所拥有的:
...
export default function App() {
const [currentDateTime, setCurrentDateTime] = useState(() => new Date().toLocaleString());
useEffect(() => {
const secondsTimer = setInterval(() => {
setCurrentDateTime(new Date().toLocaleString());
}, 1000);
return () => clearInterval(secondsTimer);
}, [setCurrentDateTime]);
console.log('RENDERING');
<Text>{currentDateTime}</Text>
...
我可以看到控制台日志每秒在渲染。
有没有一种方法可以避免这种重新渲染并仍然更新currentDateTime
答案 0 :(得分:0)
如果我理解您的意思,那么您想在不触发React生命周期的情况下更新DOM。可以使用refs(请参阅React.useRef):
import * as React from "react";
import "./styles.css";
export default function App() {
const dateTimeRef = React.useRef<HTMLSpanElement>(null);
console.log("RENDERING");
React.useEffect(() => {
const secondsTimer = setInterval(() => {
if (dateTimeRef.current) {
dateTimeRef.current.innerText = new Date().toLocaleString()
}
}, 1000);
return () => clearInterval(secondsTimer);
}, []);
return <span ref={dateTimeRef} />;
}
查看工作演示-https://codesandbox.io/s/nice-snow-kt500?file=/src/App.tsx
如果您要使用Text
之类的组件,则该组件将必须将引用转发到dom,例如:
import * as React from "react";
import "./styles.css";
const Text = React.forwardRef<HTMLSpanElement>((props: any, ref) => {
console.log("RENDERING TEXT")
return <span ref={ref}></span>
});
export default function App() {
const dateTimeRef = React.useRef<HTMLSpanElement>(null);
console.log("RENDERING APP");
React.useEffect(() => {
const secondsTimer = setInterval(() => {
if (dateTimeRef.current) {
dateTimeRef.current.innerText = new Date().toLocaleString();
}
}, 1000);
return () => clearInterval(secondsTimer);
}, []);
return <Text ref={dateTimeRef} />;
}
查看工作演示-https://codesandbox.io/s/jolly-moon-9zsh2?file=/src/App.tsx
答案 1 :(得分:0)
考虑使用shouldComponentUpdate生命周期方法;目的是防止不必要的渲染。添加此方法,并告诉您的组件不要更新状态的这一特定部分。例如,您可以添加此shouldComponentUpdate()来拒绝超过
的更新// Example logic for only re-rendering every 5 seconds; Adapt as needed.
shouldComponentUpdate(nextProps, nextState) {
if (this.lastUpdatedTimeInSeconds+5 >= nextState.timeinseconds) {
return false;
}
this.lastUpdatedTimeInSeconds = nextState.timeinseconds
return true;
}
答案 2 :(得分:0)
Eliya Cohen的回答在概念上是正确的。为了避免重新渲染,我们不能使用带间隔的状态。我们需要引用该元素。不幸的是,我无法以相同的方式将Eliya的React代码用于React Native,所以我做了更多的挖掘工作,并在directly manipulating React Native components上找到了文档。
简而言之,您可以操纵内置RN组件的PROPS,并通过不更改状态来避免重新渲染。
由于<Text>
组件未使用道具来设置其值,例如<Text text="my text" />
,因此我们无法使用此方法来更新它。但是,有效的方法是更新TextInput
的值,因为它是由value
道具设置的。为了使<TextInput>
像<Text>
一样,我们要做的就是将其属性editable
设置为false,当然要避免使用默认样式来使其看起来像输入
这是我的解决方案。如果有人有更好的建议,请提出建议。
import React, { useEffect } from 'react';
import { TextInput } from 'react-native';
const Timer: React.FC = () => {
updateTime = (currentTime) => {
time.setNativeProps({ text: currentTime });
};
useEffect(() => {
const secondsTimer = setInterval(() => {
updateTime(new Date().toLocaleString());
}, 1000);
return () => clearInterval(secondsTimer);
}, []);
return <TextInput ref={(component) => (time = component)} editable={false} />;
};
export default Timer;