React本机组件生命周期:`ref`用法和`null`对象

时间:2018-04-09 16:12:49

标签: reactjs react-native

我有一个父组件index.js



  render() {
    const { firstName, token } = this.props.user;
  
    if (token && firstName) {
      return (
        <View style={{ flex: 1 }}>
          <HomeRoot />
        </View>
      );
    }

    console.log('=== ELSE');
    return (
      <View style={{ flex: 1 }}>
        <SplashScreen />
      </View>
    );
  }
}
&#13;
&#13;
&#13;

用户未登录时显示的SplashScreen:

&#13;
&#13;
// Methods imports.
import React from 'react';
import { View, Text, Image, TouchableOpacity, StyleSheet } from 'react-native';
import { connect } from 'react-redux';
import { Asset, AppLoading, Font, DangerZone } from 'expo';

import FadeInView from '../animations/FadeInView';

// Redux actions
import { signinUser } from '../../store/actions/actions';

const { Lottie } = DangerZone;

const styles = StyleSheet.create({
  wrapper: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  // ...
});

function cacheImages(images) {
  return images.map(image => {
    if (typeof image === 'string') {
      return Image.prefetch(image);
    }

    return Asset.fromModule(image).downloadAsync();
  });
}

function cacheFonts(fonts) {
  return fonts.map(font => Font.loadAsync(font));
}

class SplashScreen extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isReady: false
    };
    this.bgAnim = null;
  }

  setBgAnim(anim) {
    // if (anim === null) {
    //   return;
    // }
    this.bgAnim = anim;
    this.bgAnim.play();
  }

  async loadAssetsAsync() {
    const imageAssets = cacheImages([
     // ...
    ]);

    const fontAssets = cacheFonts([{
      'cabin-bold': CabinBold,
      'league-spartan-bold': LeagueSpartanBold
    }]);

    await Promise.all([...imageAssets, ...fontAssets]);
  }

  render() {
    if (!this.state.isReady) {
      return (
        <AppLoading
          startAsync={this.loadAssetsAsync}
          onFinish={() => this.setState({ isReady: true })}
        />
      );
    }

    return (
      <View style={styles.wrapper}>
        <Lottie
          ref={c => this.setBgAnim(c)}
          resizeMode="cover"
          style={{
            position: 'absolute',
            zIndex: 1,
            left: 0,
            top: 0,
            width: '100%',
            height: '100%',
          }}
          source={require('../../../assets/SPLASH_03.json')}  // eslint-disable-line
        />
      </View>
    );t
  }
}

export default connect(
  null,
  { signinUser }
)(SplashScreen);
&#13;
&#13;
&#13;

signinUser调用facebookAuth,然后将获取的用户个人资料和令牌存储在一个唯一的dispatch中。

此时index.js

token && firstName为真,SplashScreen组件应该让他的位置HomeRoot

然而,它在SplashScreen渲染方法崩溃:ref={c => this.setBgAnim(c)}。如果我们删除此行,或者在cc时检查放弃null,一切都按预期工作。

为什么c中的ref={c => this.setBgAnim(c)}在此阶段为空?

如何以比检查null更好的方式处理此问题?

enter image description here

1 个答案:

答案 0 :(得分:3)

From docs

  

当组件安装时,React将使用DOM元素调用ref回调,并在卸载时调用null。在componentDidMount或componentDidUpdate生命周期挂钩之前调用ref回调。

知道在某些点传递给回调的ref将为null,只需进行检查:

setBgAnim(anim) {
  this.bgAnim = anim;
  if(anim) {
    this.bgAnim.play();
  }
}

我不认为这种方法有问题。

相关问题