Таймер React + Redux. React не отправляет действие по таймеру (SetInterval) в ComponentDidMount - PullRequest
1 голос
/ 27 мая 2020

Я пытаюсь сделать таймер в своем приложении с помощью React + Redux. Итак, у меня есть родительский компонент:

import React, { Component } from "react";
import { connect } from "react-redux";
import { compose } from "redux";

import QuestionCounter from "../question-counter";
import FinishButton from "../finish-button";
import TimeCounter from "../time-counter";
import PauseButton from "../pause-button";

import testFinished from "../../actions/test-finished";
import timerTick from "../../actions/timer-tick";
import setTimer from "../../actions/set-timer";

import totalWithEwStruct from "../hoc/total-with-ew-structure";
import withIndicators from "../hoc/with-indicators";

const Total = ({ total, testFinished }) => {
  const { finishedCount, totalCount, isPaussed, timeLeft } = total;
  return (
    <div className="test-total">
      <QuestionCounter
        finishedCount={finishedCount}
        totalCount={totalCount}
        testFinished={testFinished}
      />
      <FinishButton testFinished={testFinished} />
      <TimeCounter
        timeLeft={timeLeft}
        testFinished={testFinished}
        setTimer={setTimer}
        timerTick={timerTick}
      />
      <PauseButton isPaussed={isPaussed} />
    </div>
  );
};

const mapStateToProps = ({ total, loading, error }) => {
  return { total, loading, error };
};

const mapDispatchToProps = {
  testFinished,
  setTimer,
  timerTick
}

export default compose(
  totalWithEwStruct(),
  connect(mapStateToProps, mapDispatchToProps),
  withIndicators()
)(Total);

Я пытаюсь использовать timerTick по таймеру в componentDidMount

import React, { Component } from "react";

export default class TimeCounter extends Component {
  componentDidMount() {
    const { setTimer, timerTick } = this.props;
    let timer = setInterval(() => {
      timerTick();
      console.log("tick");
    }, 1000);
    setTimer(timer);
  }

  componentDidUpdate() {
    const { timeLeft, testFinished } = this.props;
    if (timeLeft <= 0) {
      testFinished();
    }
  }

  render() {
    const { timeLeft } = this.props;
    return (
      <div className="question-counter__timeleft">
        Времени осталось
        <span className="question-counter__timer">{timeLeft}</span>
      </div>
    );
  }
}

Итак, я вижу «тик» - «тик» - «тик» в консоли, но React не отправляет мою функцию timerTick() редуктору. Я попытался войти в консоль action.type для отладки, но timerTick не действует

const timerTick = () => {
  return {
    type: "TIMER_TICK"
  };
};

export default timerTick;

Код действия

Я не понимаю, почему это не так не работает.

Ответы [ 3 ]

0 голосов
/ 27 мая 2020

Вам необходимо добавить отправку тика таймера внутри компонента тика таймера. Поскольку дочерний компонент не осведомлен о действиях.

Подробнее см. Ссылку ниже: https://itnext.io/dispatching-actions-from-child-components-bd292a51f176

0 голосов
/ 27 мая 2020

Ответ

если ваш компонент не подключен к redux, вы не сможете отправить какое-либо действие.

Что я имею в виду?

Пример

import React from “react”;
import { connect } from “react-redux”;

class MyCom extensa React.Component {

    componentDidMount () {
          const { action } = this.props;

          action();
     }

     render () {
     .....
     }
}

const toState = state => ({....});
const toDispatch = {
   action
};

export default connect(toState, toDispatch)(MyCom);

Объясняет

По сути, connect from ”react-redux” - это HO C компонент высокого порядка, который в javascript мире: не что иное, как функция высокого порядка. функция, возвращающая другую функцию.

0 голосов
/ 27 мая 2020

Компонент Total должен принимать timerTick функцию из props, которая связана с хранилищем redux, поскольку вы добавили его в mapDispatchToProps.

Если вы не деструктурируете его из props, ccomponent будет использовать импортированную функцию, которая не является созданным действием, если она не передана в dispatch function

const Total = ({ total, testFinished }) => {
  const { finishedCount, totalCount, isPaussed, timeLeft, timerTick } = total;
  return (
    <div className="test-total">
      <QuestionCounter
        finishedCount={finishedCount}
        totalCount={totalCount}
        testFinished={testFinished}
      />
      <FinishButton testFinished={testFinished} />
      <TimeCounter
        timeLeft={timeLeft}
        testFinished={testFinished}
        setTimer={setTimer}
        timerTick={timerTick}
      />
      <PauseButton isPaussed={isPaussed} />
    </div>
  );
};
...