在 React Native 使用 setInterval

最後更新於 2022 年 6 月 17 日

最近手上的一個案子要求所有的數據必須實時更新(每秒或每分鐘),且因為後端不用 socket 我需要自行在前端做處理,於是我就想著用 setInterval 來解決吧。這篇文章簡單紀錄一下使用 setInterval 用到的小技巧,方便之後回顧。

定時器的基本使用

最基本的 setInterval 使用方式如下:

useEffect(() => {
    const interval = setInterval(loadData, 1000); // 每隔一秒執行 loadData 這個 function
    return () => clearInterval(interval);
  }, []);

useEffect 中的 return 就是類式組件生命週期中的 componentWillUnmount,通常用於取消訂閱、清除定時器…等。

刪除指定的定時器

有時候你的頁面會需要好幾個定時器,但你可能想指定清除其中一個的時候,可以用 useRef 將 interval ID 存下來,然後將之刪除:

import React, { useRef } from "react";
// ...
const interval = useRef(null);

useEffect(() => {
    interval.current = setInterval(loadData, 1000);
}, []);

const handlePause = () => {
    clearInterval(interval.current);
}

如果想要跨頁面刪除的話,也可以將 interval ID 存進 context 裡面:

/* src/cotext.js */
import React from "react";

export default Context = React.createContext({
  statusBarHeight: null,
});
/* src/App.js */
import Context from "./context";
import React, { useState } from "react";

export default function App() {
  const [intervalId, setIntervalId] = useState();

  return (
    <Context.Provider
      value={{
        intervalId, // 將要共用的變數(數據)添加在這
        setIntervalId
      }}
    >
      <Column flex={1} style={{ position: "relative" }}>
        {body}
      </Column>
    </Context.Provider>
  );
}
/* /src/screen/Home.js */
import React, { useState, useEffect, useContext } from "react";
import Context from "../context";

export default function Home() {
  const { intervalId, setIntervalId } = useContext(Context);
  const interval = useRef(null);

  useEffect(() => {
     interval.current = setInterval(loadData, 1000);
     setIntervalId(interval.current); // 將 interval ID 存起來
  }, []);
  // ...
}

監聽路由變化的同時開關定時器

useRef

在路由變化的時候建立新的定時器,並且在前往別的頁面時將定時器清除:

import React, { useEffect, useRef } from "react";
import { View, Button } from "react-native";
import { useNavigation } from "@react-navigation/core";

export default function Home() {
  const navigation = useNavigation();
  const interval = useRef(null);

  useEffect(() => {
    const unsubscribe = navigation.addListener("focus", () => {
        handlePause();
        interval.current = setInterval(loadData, 1000);
    });
    return unsubscribe;
  }, []);

  const loadData = () => {
    // ...
  }

  const handleNavigate = () => {
    clearInterval(interval.current);
    navigation.navigate("Clients");
  }

  const handlePause = () => {
    clearInterval(interval.current);
  }

  return (
    <View style={{ flex: 1 }}>
      <Button title="Clients" onPress={handleNavigate} />
    </View>
  )
}

全局變數

還有一種很簡單的寫法,就是將定時器的 id 透過全局變數存著,然後一樣使用 useEffect return 時清除定時器即可。

let intervalId = null;

const Home = () => {

  useEffect(() => {
    loadData();

    return () => {
      clearInterval(intervalId);
    }
  }, []);

  const loadData = () => {
    intervalId = setInterval(() => {
      getData();
    }, 1000);
  }

  // ...
}

還有些等我慢慢回憶一下吧.. 忘記了,哈哈😂

0 0 評分數
Article Rating
訂閱
通知
guest

0 Comments
在線反饋
查看所有評論