Реагировать на нативный Animated undefined не является объектом (оценка «u.stopTracking») - PullRequest
0 голосов
/ 17 января 2019

У меня следующая проблема: "undefined is not an object (evaluating 'u.stopTracking')".

Это происходит, когда на Expo я обновляю props, я пытался использовать на componentWillReceiveProps, stopAnimation() и stopTracking(), но не смог.

Ссылка экспо: Здесь

Чтобы появилась ошибка, просто нажмите на изображение центрального игрока.

Может кто-нибудь помочь мне?

App:

import * as React from 'react';
import { Text, View, StyleSheet, ImageBackground } from 'react-native';
import { Constants } from 'expo';

import Album from './Album';
import Track from './Track';
const State = ['normal', 'transparent', 'big'];

export default class App extends React.Component {
  constructor() {
    super();
    this.state = {
      type: 0,
    };
  }

  render() {
    let { type } = this.state;
    return (
      <View style={styles.container}>
        <ImageBackground
          source={{
            uri:
              'https://i.pinimg.com/originals/62/6f/84/626f84c40696c1308a77fd8331e12b3e.jpg',
          }}
          imageStyle={{ borderRadius: 4 }}
          style={{
            alignItems: 'center',
            justifyContent: 'center',
            height: 400,
            width: 400,
          }}>
          <Album
            type={State[type]} //normal,transparent,big
            title={Track.name}
            artist={Track.artists[0].name}
            cover={Track.album.images[0].url}
            onPress={() => {
              type = ++type % 3;
              this.setState({ type });
            }}
          />
        </ImageBackground>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#fff',
  },
});

Альбом:

import * as React from 'react';
import {
  Text,
  View,
  StyleSheet,
  ImageBackground,
  Animated,
  TouchableOpacity,
} from 'react-native';
const size = 40;

export default class Album extends React.Component {
  constructor(props) {
    super(props);
    this.min = size / 4;
    this.max = size / 2;
    this.heightCenter = new Animated.Value(this.min);
    this.heightLateral = new Animated.Value(size / 2);
    /*this.state = {
      heightCenter: new Animated.Value(this.min),
      heightLateral: new Animated.Value(size / 2),
    };*/
  }

  animateBar = (el, value) => {
    var newValue = value == this.max ? this.min : this.max;
    Animated.timing(el, {
      toValue: value,
    }).start(() => this.animateBar(el, newValue));
  };

  onPress = e => {
    return this.props.onPress(e);
  };

  componentDidMount() {
    console.log(this.heightCenter)
    this.animateBar(this.heightCenter, this.min);
    this.animateBar(this.heightLateral, this.max);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.type !== this.props.type) {
      console.log('componentWillReceiveProps');
      //this.state.heightCenter.stopAnimation();
      //this.state.heightLateral.stopAnimation();
      //Animated.stopTracking();
      //Animated.timing(this.heightCenter).stopTracking();
      //Animated.timing(this.heightLateral).stopTracking();
      /*this.state.heightCenter.stopTracking();
      this.state.heightLateral.stopTracking();
      this.state.heightCenter.stopAnimation();
      this.state.heightLateral.stopAnimation();*/
      //this.heightCenter = {};
      //this.heightLateral = null;
      //this.heightCenter.stopTracking();
      //this.heightLateral.stopTracking();
      //this.state.heightCenter.stopAnimation();
      //this.state.heightLateral.stopAnimation();
      console.log(this.heightCenter)
    }
  }

  componentDidUnmount() {
    console.log('componentDidUnmount');
    //Animated.timing(this.heightCenter).stop();
    //Animated.timing(this.heightLateral).stop();
  }

  componentDidUpdate() {
    this.animateBar();
  }

  render() {
    let { type, title, artist, cover } = this.props;
    let barWidthCenter = {
      height: this.heightCenter,
    };
    let barWidthLateral = {
      height: this.heightLateral,
    };
    if (type != 'normal' && type != 'transparent' && type != 'big')
      type = 'transparent';
    let backgroundColor =
      type == 'normal' ? 'rgba(255,255,255,1)' : 'rgba(255,255,255,0.5)';
    let color = type == 'normal' ? '#000' : '#fff';
    if (type == 'big')
      return (
        <TouchableOpacity onPress={() => this.onPress()}>
          <View
            style={{
              alignItems: 'center',
              justifyContent: 'center',
            }}>
            <ImageBackground
              source={{
                uri: cover,
              }}
              imageStyle={{ borderRadius: 4 }}
              style={{
                flexDirection: 'row',
                alignItems: 'flex-end',
                justifyContent: 'flex-start',
                height: 200,
                width: 200,
              }}>
              <View
                style={{
                  borderRadius: 4,
                  flexDirection: 'row',
                  alignItems: 'center',
                  justifyContent: 'center',
                  backgroundColor: 'rgba(0,0,0,0.3)',
                  padding: 5,
                  height: 40,
                  width: 40,
                  margin: 5,
                }}>
                <Animated.View
                  style={[
                    {
                      backgroundColor: 'rgba(255,255,255,1)',
                      width: 5,
                      borderRadius: 5 / 2,
                      margin: 2,
                    },
                    barWidthLateral,
                  ]}
                />
                <Animated.View
                  style={[
                    {
                      backgroundColor: 'rgba(255,255,255,1)',
                      width: 5,
                      borderRadius: 5 / 2,
                      margin: 2,
                    },
                    barWidthCenter,
                  ]}
                />
                <Animated.View
                  style={[
                    {
                      backgroundColor: 'rgba(255,255,255,1)',
                      width: 5,
                      borderRadius: 5 / 2,
                      margin: 2,
                    },
                    barWidthLateral,
                  ]}
                />
              </View>
            </ImageBackground>
            <View style={{ paddingLeft: 12, paddingRight: 12 }}>
              <Text style={{ fontWeight: 'bold', color: '#fff' }}>{title}</Text>
              <Text style={{ color: '#fff' }}>{artist}</Text>
            </View>
          </View>
        </TouchableOpacity>
      );
    return (
      <TouchableOpacity onPress={() => this.onPress()}>
        <View
          style={{
            backgroundColor: backgroundColor,
            flexDirection: 'row',
            justifyContent: 'center',
            borderRadius: 4,
            padding: 4,
          }}>
          <ImageBackground
            source={{
              uri: cover,
            }}
            imageStyle={{ borderRadius: 4 }}
            style={{
              flexDirection: 'row',
              alignItems: 'center',
              justifyContent: 'center',
              height: size,
              width: size,
            }}>
            <Animated.View
              style={[
                {
                  backgroundColor: 'rgba(255,255,255,1)',
                  width: 5,
                  borderRadius: 5 / 2,
                  margin: 2,
                },
                barWidthLateral,
              ]}
            />
            <Animated.View
              style={[
                {
                  backgroundColor: 'rgba(255,255,255,1)',
                  width: 5,
                  borderRadius: 5 / 2,
                  margin: 2,
                },
                barWidthCenter,
              ]}
            />
            <Animated.View
              style={[
                {
                  backgroundColor: 'rgba(255,255,255,1)',
                  width: 5,
                  borderRadius: 5 / 2,
                  margin: 2,
                },
                barWidthLateral,
              ]}
            />
          </ImageBackground>
          <View style={{ paddingLeft: 12, paddingRight: 12 }}>
            <Text style={{ fontWeight: 'bold', color }}>{title}</Text>
            <Text style={{ color }}>{artist}</Text>
          </View>
        </View>
      </TouchableOpacity>
    );
  }
}

1 Ответ

0 голосов
/ 04 июня 2019

Я вижу, вы давно задавали этот вопрос. Я не знаю, как вы решили эту проблему, но у меня была та же ошибка:

"undefined is not an object (evaluating 'u.stopTracking')"

из-за кода здесь:

export default class App extends React.Component {
  constructor(props) {
    super(props);

      this.state = {
        elementPositionX: 0,
        target: null,
        marginLeft: new Animated.Value(0),
      };

Это происходило потому, что я поместил анимационную ценность в состояние. Он должен был быть определен вне состояния как свойство класса компонента, например:

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.marginLeft= new Animated.Value(0);

      this.state = {
        elementPositionX: 0,
        target: null,
      };

Документация по Animated API очень скудная, поэтому я не уверен, почему, но это решило мою проблему.

EDIT:

Мне удалось как-то перевести его в состояние, и оно работает, не давая предыдущей ошибки. Однако мне нужно использовать этот код, чтобы изменить анимированное значение: this.state.marginLeft2.setValue(amount);, и это фактически меняет состояние напрямую - без использования .setState(). Мне это не кажется хорошим.

...