如果屏幕包裹在 HOC 中,StackNavigator 屏幕的反应导航 header 不会呈现

react navigation header for StackNavigator screen doesn't render if screen wrapped in HOC

总结

  1. 我创建了一个自定义 HOC,它通过检查 redux 存储是否有 user.id 属性
  2. 来检查用户是否已通过身份验证
  3. 我正在使用 React 导航和 React Native
  4. 当我将我的屏幕组件包装在我的 HOC 中时,导航 header 出现但消失了(相反,如果我不将我的屏幕组件包装在我的 HOC 中,导航 header出现正确)
  5. 在 HOC 和包装组件中也有 react-redux connect,我想知道这是否会导致事情中断

当我将屏幕组件包装在我的自定义 HOC 中时,为什么我的反应导航 header 没有正确显示?

我想知道我是否以错误的顺序包装东西——这些是屏幕组件中可能有问题的代码行(我测试时注释掉了其中一个):

// export default connect(mapStateToProps, mapDispatchToProps)(EntityPage); <--this renders the header fine

  export default connect(mapStateToProps, mapDispatchToProps)(withAuthentication(EntityPage)); <--this renders the header blank

代码

我制作的自定义 HOC,用于检查身份验证

import React, {
  Component
} from 'react';
import PropTypes from 'prop-types';
import {
  Alert
} from 'react-native';
import {
  connect
} from 'react-redux';

function withAuthentication(Comp) {
  class AuthenticatedScreen extends Component {
    componentDidUpdate(prevProps) {
      if (this.props.user && !this.props.user.id) {
        Alert.alert('you\'re not logged in anymore');
      }
    }

    render() {
      return <Comp { ...this.props
      }
      />;
    }
  }

  function mapStateToProps(state) {
    return {
      user: state.user,
    };
  }

  AuthenticatedScreen.propTypes = {
    user: PropTypes.object,
    component: PropTypes.object,
  };

  return connect(mapStateToProps)(AuthenticatedScreen);
}

export default withAuthentication;

我用自定义身份验证 HOC 包装的屏幕组件

import withAuthentication from '../User/AuthorizedHOC'; <--my custom HOC import

class EntityPage extends Component {
    static navigationOptions = ({navigation}) => {
      return {
        title: 'My Entities',
        headerRight: (
>>        <Button type='action' title='Add New Entity' onPress={()=>navigation.navigate('EntityCreate')}>
          </Button>),
        headerStyle: {paddingRight: (Platform.OS === 'ios') ? 0 : 8},
      };
    };

    componentDidMount() {
      this.props.loadEntities();
    }

    render() {
      const {
        entities,
      } = this.props;

      return (
        <FullscreenView>
          <EntityList entities={entities}/>
        </FullscreenView>
      );
    }
  }

  function mapStateToProps(state) {
    return {
      entities: getSortedEntityList(state),
        };
  }

  function mapDispatchToProps(dispatch) {
    return {
      loadEntities: () => dispatch(loadEntities()),
      deleteEntity: (entity) => dispatch(deleteEntity(entity)),
    };
  }

  // export default connect(mapStateToProps, mapDispatchToProps)(EntityPage); <--this renders the header fine

  export default connect(mapStateToProps, mapDispatchToProps)(withAuthentication(EntityPage)); <--this renders the header blank

您可以尝试使用 redux 中的 compose 方法。 主要实用程序是

write deeply nested function transformations without the rightward drift of the code

由于connect需要原始组件,因此

用法

import {compose} from "redux"

const composedWithAuthentication = compose(
    connect(mapStateToProps, mapDispatchToProps),
    withAuthentication
);

const newWithAuth = composedWithAuthentication(EntityPage)

newWithAuth.navigationOptions = {
 // Your Options
}

这会将 navigationOptions 设置在最外层 hoc

或者更简洁的方法是使用 hoistStatics from recompose

export default hoistStatics(composedWithAuthentication)(EntityPage);

Augments a higher-order component so that when used, it copies non-react static properties from the base component to the new component.