繁体   English   中英

如何使用 Redux 定期更新和 React Hooks 处理状态?

[英]How to handle state using Redux with periodical updates and React Hooks?

我的用例

我刚刚开始使用带有 Hooks 和 Redux 的 React (Native),并且在理解我的用例的状态更新概念的某些部分时遇到了一些问题。 我目前正在开发一个 React Native 应用程序,它应该每整分钟更新一次数据。 因此,如果用户在11h:31m:27s进入应用程序,

  1. 应该显示初始状态,然后
  2. setTimeout使用偏移量处理第一次更新以达到整分钟(在本例中为33s达到11h:32m:00s
  3. setInterval从现在开始处理数据的每一次更新。

我的问题

目前,使用下面的代码, reducers.js文件中的console.log("Reducer Fires!")每隔一分钟就会越来越多地被触发(例如,第一分钟只触发一次,然后第二分钟两次,依此类推)。 所以我觉得我在如何处理我的数据状态以及setInterval()setTimeout()逻辑方面仍然做错了。 有人可以查看我下面的代码并指出我正在做的错误吗?

我的代码(到目前为止)

一些虚拟data

export const DATA = [
    {"id": 1, "myAttr": 0},
    {"id": 2, "myAttr": 4},
    {"id": 3, "myAttr": 8},
    {"id": 4, "myAttr": 12},
]

带有 redux 存储的App.js文件:

import React from 'react';
import { createStore, combineReducers } from "redux";
import { Provider } from "react-redux";
import { View } from 'react-native';

// Components
import MyComponent from "./components/MyComponent";
import dataReducer from "./store/reducers";

//Create Redux store
const rootReducer = combineReducers({
  mydata: dataReducer
});

const store = createStore(rootReducer);

export default function App() {

  return (
    <Provider store={store} >
      <View>
        <MyComponent />
      </View>
    </Provider>
  );
}

存储我的 Redux 操作的actions.js文件:

//Action to update the data
export const UPDATE_DATA = "UPDATE_DATA";

export const updateData = () => {
    return { type: UPDATE_DATA }
}

用于存储减速器的reducers.js文件:

import { DATA } from "../data/data";
import { UPDATE_DATA } from "./actions";

// Initial state when app launches
const initState = {
    data: DATA
}

const dataReducer = (state = initState, action) => {
    switch (action.type) {
        case UPDATE_DATA:
            //Update an attribute in each object of the data array

            const updatedData = state.data.map((i) => {
                const newMyAttr = i.myAttr + 1;
                return { ...i, myAttr: newMyAttr }
            }
            )

            console.log("Reducer Fires!");
            return { ...state, data: updatedData }

        default:
            return state;
    }
};

export default dataReducer;

我试图更新状态的component

import React, { useEffect, useCallback } from "react";
import { useSelector, useDispatch } from "react-redux";
import { Text, View } from 'react-native';

const MyComponent = (props) => {
    const myData = useSelector(state => state.mydata.data);

    let start = new Date();
    const fullMinuteOffset = (60 - start.getSeconds()) * 1000;

    const dispatch = useDispatch();

    const saveData = useCallback(() => {
        dispatch(updateData())
    }, [dispatch]);

    useEffect(() => {
        const timer = setTimeout(() => {
            saveData()
            const interval = setInterval(() => {
                saveData()
            }, 60000)

            return () => clearInterval(interval);
        }, fullMinuteOffset);

        return () => clearTimeout(timer);
    }, [saveData, fullMinuteOffset]);

    return(
        <View>
            <Text>{myData[0].myAttr}</Text>
        </View>
    );
};

export default MyComponent;

每次组件渲染时,它都会有一个新的 fullOffserMinute 值,它是 useEffect 的依赖项,因此注册了一个新的间隔调用。

这是您的代码的简化工作示例:

https://codesandbox.io/s/jolly-panini-k35s1?fontsize=14&hidenavigation=1&theme=dark

  // the relevant part of it
  let start = new Date();
  let [counter, setCounter] = useState(0);
  const fullMinuteOffset = (60 - start.getSeconds()) * 1000;

  function timerAction() {
    setCounter(counter => counter + 1);
  };

  useEffect(() => {
    console.log("-- use effect --");
    const timer = setTimeout(() => {
      console.log("save data timeout");
      timerAction();
      const interval = setInterval(() => {
        console.log("save data interval");
        timerAction();
      }, 5000);

      return () => clearInterval(interval);
    }, fullMinuteOffset);

    return () => clearTimeout(timer);
  }, []);

如果您打算按时间间隔更新本地状态,您还应该在这里阅读答案: 在 setInterval 内使用 React 状态挂钩时状态不更新

如果您将 useEffect 依赖项更改为: [saveTime, fullMinuteOffset] -> 到[] 似乎每次 useEffect 调用的组件更新可能会注册更多间隔

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM