Как обрабатывать состояние с помощью Redux с периодическими обновлениями и React Hooks? - PullRequest
0 голосов
/ 17 февраля 2020

Мой вариант использования

Я только начинаю с React (Native) с Hooks и Redux, и у меня возникают некоторые проблемы с пониманием некоторых частей концепции обновления состояния для моего варианта использования. В настоящее время я работаю над приложением React Native, которое должно обновлять данные каждую полную минуту. Поэтому, если пользователь входит в приложение, скажем, 11h:31m:27s,

  1. , должно отображаться начальное состояние, тогда
  2. a setTimeout обрабатывает первое обновление со смещением, чтобы достичь полная минута (в данном случае 33s для достижения 11h:32m:00s)
  3. a setInterval теперь обрабатывает ежеминутное обновление данных.

My Issue

В настоящее время при использовании приведенного ниже кода console.log("Reducer Fires!") внутри файла reducers.js запускается все чаще с каждой новой минутой (например, только один раз в первую минуту, затем два раза во вторую минуту и ​​т. Д.). Поэтому я чувствую, что все еще делаю что-то не так с тем, как я обрабатываю состояние моих данных вместе с setInterval() и setTimeout() logi c. Может ли кто-нибудь просмотреть мой код ниже и указать мне на ошибки, которые я делаю?

Мой код (пока)

какой-то дурачок data:

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

App.js* Файл 1037 * с хранилищем редуксов:

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>
  );
}

Файл actions.js, в котором хранится мое действие Redux:

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

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

the 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;

Ответы [ 2 ]

1 голос
/ 17 февраля 2020

Каждый раз, когда компонент рендерится, он будет иметь новое значение 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);
  }, []);

Вы также должны прочитать ответы здесь, если вы собираетесь обновлять локальное состояние через определенные промежутки времени: Состояние не обновляется при использовании перехватчика состояния React в setInterval

1 голос
/ 17 февраля 2020

Что произойдет, если вы измените зависимости useEffect на следующее: [saveTime, fullMinuteOffset] -> на []. Кажется, что каждый раз, когда обновления компонента, которые используют вызов useEffect, могут регистрировать больше интервалов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...