React - Почему событие componentDidMount вызывается мгновенно - PullRequest
0 голосов
/ 27 февраля 2019

Я поиграл с анимацией, реализованной с reactjs.В приложении я создал автомобиль, который ездит по трассе.На этой трассе есть препятствия, которые автомобиль должен распознать.Я использую window.setInterval для повторяющихся событий.Может быть, это не лучший вариант, но на самом деле я не знаю, как это сделать.

Поскольку некоторые изменения выполняются, выполняется несколько интервалов.Но на самом деле я не знаю причину этого.Кто-нибудь может подсказать, почему компонент racer мгновенно запускается в событии componentdidmount?

Компонент Racer задает текущее положение и степень / лодыжку для компонента Track.Компонент Track сохраняет эти значения в states и присваивает его компоненту Racer как props.Но это не должно привести к мгновенному запуску события componentdidmount компонента Racer, или?

Вот мой код:

App.js

import React, { Component } from 'react';
import Track from './components/track.js';
const uuidv1 = require('uuid/v1');

class App extends Component {

  constructor(props) {
    super(props);
    this.state = { 
      obstacles: [
        {
          key: uuidv1(),
          position: {
            left: 500,
            top:10,
          },
          width: 25,
          height: 25,
        },
        {
          key: uuidv1(),
          position: {
            left: 650,
            top:60,
          },
          width: 25,
          height: 25,
        }
      ],
    };
  }

  render() {
    return (
      <div className="App">
        <Track width={800} height={100} obstacles={this.state.obstacles}>
        </Track>
      </div>
    );
  }
}

export default App;

Track.js

import React, { Component } from 'react';
import styled from 'styled-components';
import Racer from './racer.js';
import Obstacle from './obstacle';
import centralStrip from '../images/centralStrip.png';
const uuidv1 = require('uuid/v1');

class Track extends Component {

    constructor(props) {
        super(props);
        this.state = { 
            racerCurrentPosition: {
                top: 60,
                left:150
            },
            racerDegree: 0,
        };

    }

    componentDidMount() {
    }

    handleObstacleCheck(position, racerPosition) {
        let obstacleFound = false;
        obstacleFound = this.props.obstacles.map((obstacle) => {
            let returnValue = false;
            let obstacleRect = document.getElementById(obstacle.key).getBoundingClientRect();
            if( position.right >= obstacleRect.left && position.right <= obstacleRect.right && racerPosition.top >= obstacleRect.top && racerPosition.bottom <= obstacleRect.bottom) {
                returnValue =  true;
            }
            return returnValue;
        });
        let isObstacleFound = false;
        if(obstacleFound.indexOf(true) !== -1) {
           isObstacleFound = true; 
        }
        return isObstacleFound;
    }

    handleRacerPositionChange(position) {
        this.setState({
            racerCurrentPosition: position,
        });
    }

    handleRacerDegreeChange(newDegree) {
        this.setState({
            racerDegree: newDegree,
        });
    }

    render() {
        return (
            <TrackImage key={uuidv1()} 
                        id="track" 
                        width={this.props.width} 
                        height={this.props.height}>
                <Racer  key={uuidv1()} 
                        position={this.state.racerCurrentPosition} 
                        onRacerPositionChange={this.handleRacerPositionChange.bind(this)} 
                        degree={this.state.racerDegree}
                        onRacerDegreeChange={this.handleRacerDegreeChange.bind(this)}
                        obstacleFound={this.state.obstacleFound} 
                        trackWidth={this.props.width} 
                        trackHeight={this.props.height} 
                        onObstacleCheck={this.handleObstacleCheck.bind(this)} 
                />
                {
                    this.props.obstacles.map((obstacle) => {
                        return (
                            <Obstacle   key={obstacle.key} 
                                        id={obstacle.key} 
                                        position={obstacle.position} 
                                        width={obstacle.width} 
                                        height={obstacle.height} 
                            />
                        );
                    })
                }
            </TrackImage>
        );
    }
}

export default Track;

Racer.js

import React, { Component, Fragment } from 'react';
import styled from 'styled-components';
import HelperDistance from './helpers/distance.js';
import HelperCenterCar from './helpers/centerCar.js';
import racerImage from '../images/racer.png';
const uuidv1 = require('uuid/v1');

class Racer extends Component {

    constructor(props) {
        super(props);
        this.state = { 
            key: uuidv1(),
            intervalId: 0,
            speed: 0,
            helperForLeftPositioning: 0,
            helperForTopPositioning: 0,
            isMoving: false,
            collision: false,
            centerOfCarCoordinates: {
                x: 25,
                y: 12.5
            },
            obstacleFound: false,
        };
        this.start = this.start.bind(this);
        this.move = this.move.bind(this);
    }

    componentDidMount() {
        if(this.state.intervalId === 0) {
            this.start();
        }
    }

    componentWillUnmount() {
        window.clearInterval(this.state.intervalId);
    }

    start() {
        this.setState({
            speed: 3,
            isMoving: true,
        }, () => {
            this.createInterval();
        });
    }

    stop() {
        this.setState({
            speed: 0,
            isMoving: false,
        }, () => {
            window.clearInterval(this.state.intervalId);
        });
    }

    move() {
        if(this.state.obstacleFound === true) {
            let newDegree;
            if(this.props.degree === 0) {
                newDegree = 360;
            }
            newDegree--;
            this.props.onRacerDegreeChange(newDegree);
        }
        this.step();
    }

    step() {
        if(this.state.isMoving) {
            //...calculate new position

            this.setState({
                helperForTopPositioning: helperForTopPositioning,
                helperForLeftPositioning: helperForLeftPositioning,
            },() => {
                let position = {
                    left: positionNewLeft,
                    top: positionNewTop
                };
                this.props.onRacerPositionChange(position);
            });
        }
    }

    createInterval = () => {
        let intervalId = window.setInterval(() => {
            this.move();
            console.log("IntervalId: " + intervalId);
        },100);
        this.setState({
            intervalId: intervalId,
        })
    }

    handleDistanceChange(position) {
        let racerRect = document.getElementById(this.state.key).getBoundingClientRect();
        let obstacleFound = this.props.onObstacleCheck(position, racerRect);
        if(this.state.obstacleFound !== obstacleFound) {
            this.setState({
                obstacleFound: obstacleFound
            });
        }
    }

    render() {
        return (
            <Fragment>
                <Car key={this.state.key} id={this.state.key}  position={this.props.position} degree={this.props.degree}>
                    <HelperCenterCar key={uuidv1()} position={this.state.centerOfCarCoordinates} degree={this.props.degree} />
                    <HelperDistance key={uuidv1()} onChange={this.handleDistanceChange.bind(this)} position={this.state.centerOfCarCoordinates} degree={this.props.degree} />
                </Car>
            </Fragment>
        );
    }
}

export default Racer;

HelperCenterCar и HelperDistance являютсякомпоненты, которые помогают определить, есть ли препятствие на пути.Я выложу только код HelperDistance, потому что здесь мгновенно запускаются state обновления.

HelperDistance.js

import React, { Component } from 'react';
import styled from 'styled-components';
const uuidv1 = require('uuid/v1');

class HelperDistance extends Component {

    constructor(props) {
        super(props);
        this.state = { 
            key: uuidv1(),
        };

    }

    componentDidMount() {
        this.handleOnChange();
    }

    componentDidUpdate(prevProps, prevState, snapshot) {
        this.handleOnChange();
    }

    handleOnChange() {
        let position = document.getElementById(this.state.key).getBoundingClientRect();
        this.props.onChange(position);
    }

    render() {
        return (
            <Line id={this.state.key} key={this.state.key} position={this.props.position} degree={this.props.degree} />
        );
    }
}

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