F
F
funkydance2019-11-05 11:22:27
JavaScript
funkydance, 2019-11-05 11:22:27

Animating numbers in React, what am I doing wrong?

Good day everyone.
I want to make an animation of numbers, for this I chose the library
https://github.com/glennreyes/react-countup
I connected it, in the render I output: As a result, I get a black screen, and in the console the error is:
<CountUp end= { 100 } />

Uncaught (in promise) TypeError: React__default.createRef is not a function at new CountUp (index.js:318)

Full code
/* @flow */
import React from "react";
import isEqual from "lodash/isEqual";
import { stringify as b } from "rebem-classname";
import { withLocalize } from "react-localize-redux";
import { Translate } from 'react-localize-redux';
import CountUp from 'react-countup';
import Player from "./Player";
import Clan from "./Clan";
import "./Players.scss";
import type { PlayerType, GeneralType } from "../types";

function secondsToClock(_seconds, delim = ":") {
  const minutes = Math.floor(_seconds / 60);
  const seconds = _seconds - (minutes * 60);
  return `00${minutes}`.slice(-2) + delim + `00${seconds}`.slice(-2);
}

const block = "players";

class Players extends React.Component {
  state = {
    width: 0,
    playerWidth: 0,
    offset: 0,
    isShowArrows: false,
    isShowView: true,
  };

  componentDidMount() {
    setTimeout(() => this.updatePlayers(), 0);
  }

  componentWillReceiveProps(nextProps) {
    if (!isEqual(nextProps.players, this.props.players)) {
      this.setState({ isShowView: false }, () =>
        setTimeout(() => this.setState({ isShowView: true }), 10),
      );
    }
  }

  componentDidUpdate(prevProps) {
    if (!isEqual(prevProps.players, this.props.players)) {
      this.updatePlayers();
    }
  }
  
  props: {
    state: "WAITING" | "COUNTDOWN" | "CULMINATION" | "ENDED",
    players: PlayerType[],
    general: GeneralType[],
    gameId: number,
    fund: number,
    timer: number,
  };

  updatePlayers = () => {
    const { players, general } = this.props;

    const playersLength = players.length;
    if (playersLength <= 0 || !this.view) return;

    const idx = general.length - 1;
    let player = this.view.children[0].children[idx];
    let playerMargin = parseFloat(window.getComputedStyle(player).marginLeft);
    if (player.className === "clan") {
      player = player.children[0].children[general[idx].players.length - 1];
      if (playerMargin <= 0) {
        playerMargin = parseFloat(window.getComputedStyle(player).marginLeft);
      }
    }
    const playerWidth = player.offsetWidth + playerMargin;
    const width = (playersLength * playerWidth) - playerMargin;
    this.setState({
      width,
      playerWidth,
      isShowArrows: this.view.clientWidth < width,
    });
  };



  handleArrow = d => () => {
    const { width, playerWidth, offset } = this.state;
    const maxOffset = width - this.view.clientWidth;
    let newOffset = offset + (d * playerWidth);
    if (newOffset < 0) {
      newOffset = 0;
    } else if (newOffset > maxOffset) {
      newOffset = maxOffset;
    }
    this.setState({ offset: newOffset });
  };

  render() {
    const { state, players, general, timer, fund, gameId } = this.props;
    const { width, offset, isShowArrows, isShowView } = this.state;

    return (
      <div
        className={b({
          block,
          mods: {
            show: (state === "WAITING" || state === "COUNTDOWN") && players.length > 0,
          },
        })}
      >
        <div className={b({ block, elem: "container" })}>
          <button
            className={b({ block, elem: "arrow-btn" })}
            hidden={!isShowArrows}
            onClick={this.handleArrow(-1)}
          >
            <i className="fa fa-chevron-left" />
          </button>
          <div
            className={b({ block, elem: "view", mods: { show: isShowView } })}
            ref={view => {
              this.view = view;
            }}
          >
            <div
              className={b({ block, elem: "list" })}
            >
              {general.map((obj: GeneralType) => {
                if (obj.clanId) {
                  if (obj.players.length === 1) {
                    const player = obj.players[0];
                    return <Player key={`p${player.userId}`} player={player} />;
                  }
                  return <Clan key={`c${obj.clanId}`} clan={obj} />;
                }
                return <Player key={`p${obj.userId}`} player={obj} />;
              })}
            </div>
          {/* Игра #{gameId} */}
            <div className={b({ block, elem: "time-bank"})}>
              <div className={b({ block, elem: "time"})}>
                {secondsToClock(timer)}
              </div>
              <div className={b({ block, elem: "bank"})}>
              <i className="fa fa-database" />
              < CountUp end= { 100 } /> 
              &nbsp; {fund}
              </div>

            </div>

            <div
              className={b({ block, elem: "lists" })}
            >
              {general.map((obj: GeneralType) => {
                if (obj.clanId) {
                  if (obj.players.length === 1) {
                    const player = obj.players[0];
                    return <Player key={`p${player.userId}`} player={player} />;
                  }
                  return <Clan key={`c${obj.clanId}`} clan={obj} />;
                }
                return <Player key={`p${obj.userId}`} player={obj} />;
              })}
            </div>
          </div>
          <button
            className={b({ block, elem: "arrow-btn" })}
            hidden={!isShowArrows}
            onClick={this.handleArrow(1)}
          >
            <i className="fa fa-chevron-right" />
          </button>
        </div>
      </div>
    );
  }
}

export default withLocalize(Players);

Answer the question

In order to leave comments, you need to log in

1 answer(s)
N
Nikolay Matyushkin, 2019-11-08
@Devilz_1

<div className={b({ block, elem: "time-bank"})}>
              <div className={b({ block, elem: "time"})}>
                {secondsToClock(timer)}
              </div>
              <div className={b({ block, elem: "bank"})}>
              <i className="fa fa-database" />
              < CountUp end= { 100 }>
                     {({ countRef }) => (
                          <span ref={countRef}></span>
                      )}
              </CountUp> 
              &nbsp; {fund}
              </div>

            </div>

If it's still relevant, try this.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question