我在一个名为Details
的屏幕上进行了测试:
export class Details extends Component {
static propTypes = {
auth: PropTypes.object,
checkingUserMembership: PropTypes.bool,
checkUserMembership: PropTypes.func,
fetchSelectedEvent: PropTypes.func,
isLapsedMember: PropTypes.bool,
isMember: PropTypes.bool,
loadingSelectedEvent: PropTypes.bool,
navigation: PropTypes.object,
primaryIndividual: PropTypes.object,
selectedEvent: PropTypes.object,
selectedPrice: PropTypes.object,
setSelectedPrice: PropTypes.func,
userKey: PropTypes.string,
userOrganization: PropTypes.object,
};
static navigationOptions = ({navigation}) => ({
title: navigation.state.params.title,
});
constructor(props) {
super(props);
const prices = getDetailPrices(this.props);
this.state = {
userOpenedMemberLink: false,
appState: AppState.currentState,
...prices,
};
}
componentDidMount() {
this.props.fetchSelectedEvent();
this.props.checkUserMembership();
AppState.addEventListener('change', this._handleAppStateChange);
if (this.props.isMember && !this.props.isLapsedMember) {
this._selectMemberPrice();
}
}
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
}
_selectMemberPrice = () => {
const price = this.state.individualPrices.find(p => p.IsMemberPrice);
if (price) {
this.props.setSelectedPrice(price);
}
};
_handleAppStateChange = async appState => {
if (
this.state.appState.match(/inactive|background/) &&
appState === 'active'
) {
this.props.checkUserMembership();
}
};
_validateCapacity = selectedEvent => {
if (selectedEvent.NumberOfSeatsAvailable === 0) {
Alert.alert(
'Capacity Exceeded',
capacityLimit,
[
{
text: 'OK',
onPress: () => false,
style: 'cancel',
},
],
{cancelable: false}
);
return false;
}
return true;
};
_alertNoTableSeats = () => {
Alert.alert(
'Capacity Exceeded',
capacityLimitTable,
[
{
text: 'OK',
onPress: () => false,
style: 'cancel',
},
],
{cancelable: false}
);
};
_navigate = () => {
const {selectedEvent, isMember, selectedPrice, isLapsedMember} = this.props;
const hasSeats = this._validateCapacity(selectedEvent);
if (hasSeats) {
if (selectedEvent.IsFree) {
//eslint-disable-next-line
if (selectedEvent.IsMembersOnly && (!isMember || isLapsedMember)) {
this._alertMembershipIssue();
} else {
this.props.navigation.navigate('EventRegistration');
}
} else if (selectedPrice) {
//eslint-disable-next-line
this.props.navigation.navigate("EventRegistration");
} else {
Alert.alert(
'Event Pricing',
'Please select a price before continuing.',
[
{
text: 'OK',
onPress: () => false,
style: 'cancel',
},
],
{cancelable: false}
);
}
}
};
_loginAsMember = (price = null) => {
this.props.navigation.navigate('MembershipConfirmation', {price});
};
_canSelectPrice = price => {
if (price.IsMemberPrice && this.props.isLapsedMember) {
return false;
}
if (!this.props.isMember && price.IsMemberPrice) {
return false;
}
return true;
};
_tableSeatsAvailable = price => {
if (
price.IsTable &&
this.props.selectedEvent.NumberOfSeatsAvailable < price.NumberOfSeats
) {
return false;
}
return true;
};
_selectPrice = async price => {
const canSelect = this._canSelectPrice(price);
if (canSelect) {
const tableSeatsAvailable = this._tableSeatsAvailable(price);
if (tableSeatsAvailable) {
this.props.setSelectedPrice(price);
} else {
this._alertNoTableSeats();
}
} else {
this._alertMembershipIssue(price);
}
};
_alertMembershipIssue = (price = null) => {
const {isLapsedMember, userKey} = this.props;
const buttons = [
{
text: isLapsedMember ? 'Renew Membership' : 'Join NFIB',
onPress: () => {
let url = `${env.membershipJoinLink}=${userKey}`;
if (isLapsedMember) {
const {userOrganization, primaryIndividual} = this.props;
const {PostalCode: zip} = userOrganization.Addresses[0];
const lastName = primaryIndividual.PersonalDetails.LastName;
const memberID = userOrganization.Id;
//prettier-ignore
url = `${env.membershipRenewLink}?lname=${lastName}&mid=${memberID}&zip=${zip}`;
}
Linking.openURL(url);
this.setState({userOpenedMemberLink: true});
},
},
{
text: 'Cancel',
onPress: () => false,
style: 'cancel',
},
];
if (!isLapsedMember) {
buttons.unshift({
text: 'I am a Member',
onPress: () => this._loginAsMember(price),
});
}
Alert.alert(
isLapsedMember ? 'Renew Membership' : 'Members Only',
memberMsg,
buttons,
{cancelable: false}
);
};
render() {
if (this.props.loadingSelectedEvent) {
return <Loading />;
}
return (
<EventDetails
event={this.props.selectedEvent}
handleRegistrationButtonPress={this._navigate}
handleSelectPrice={this._selectPrice}
tablePrices={this.state.tablePrices}
individualPrices={this.state.individualPrices}
selectedPrice={this.props.selectedPrice}
checkingUserMembership={this.props.checkingUserMembership}
/>
);
}
}
Details
是EventDetails
的父级,并且有一个名为PhoneEventDescription
的兄弟姐妹,如下所示:
import React from 'react';
import styles from 'events/styles';
import {View, Text} from 'react-native';
import PropTypes from 'prop-types';
import {Card, WebViewAutoHeight} from 'common-components';
import {feedContentStyles} from 'theme';
import PriceRow from './PriceRow';
import {moderateScale} from 'react-native-size-matters';
const propTypes = {
event: PropTypes.object.isRequired,
handleSelectPrice: PropTypes.func.isRequired,
individualPrices: PropTypes.arrayOf(PropTypes.object),
selectedPrice: PropTypes.object,
tablePrices: PropTypes.arrayOf(PropTypes.object),
};
//prettier-ignore
const getHTML = event => `<body style="font-family: -apple-system, Roboto, sans-serif; font-size: ${moderateScale(14, 0.2)}px;">${event.LongDescription}</body>`;
const PhoneEventDescription = props => {
const {
event,
handleSelectPrice,
individualPrices,
selectedPrice,
tablePrices,
} = props;
const displayPrices =
!event.IsRestricted &&
!event.IsFree &&
(individualPrices.length > 0 || tablePrices.length > 0);
return (
<View style={{flex: 1}}>
<Card style={styles.cardStyles} tappable={false}>
<Text style={styles.contentTitle}>{'Description'}</Text>
{event.LongDescription ? (
<WebViewAutoHeight
source={{
html: getHTML(event),
}}
/>
) : (
<Text style={feedContentStyles.parragraph}>
{event.ShortDescription}
</Text>
)}
</Card>
该子组件导致了此错误:
Warning: Failed prop type: AutoHeightWebView: prop type `source` is invalid; it must be a function, usually from the `prop-types` package, but received `undefined`.
Warning: Stateless function components cannot be given refs. Attempts to access this ref will fail.
AutoHeightWebView
的来源是什么?这是什么警告,我该如何解决?
似乎它引用了以下软件包:"react-native-autoheight-webview": "0.6.1",
,但是这里到底有什么问题呢?我对这个软件包不熟悉。
它是从此处的WebViewAutoHeight
通用组件导入的:
import React from 'react';
import PropTypes from 'prop-types';
import {StyleSheet, Dimensions} from 'react-native';
import AutoHeightWebView from 'react-native-autoheight-webview';
const {width} = Dimensions.get('window');
const WebViewAutoHeight = props => (
<AutoHeightWebView
style={[styles.webview, props.style ? props.style : {}]}
{...props}
/>
);
const styles = StyleSheet.create({
webview: {
width: width - 31,
},
});
WebViewAutoHeight.propTypes = {
source: PropTypes.object.isRequired,
style: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
};
export {WebViewAutoHeight};
答案 0 :(得分:0)
我可能是WebViewAutoHeight组件react-native-autoheight-webview npm软件包。 只需检查您的package.json文件即可。