#javascript #react-native #conditional-rendering
#javascript #react-native #условный-рендеринг
Вопрос:
У меня есть список, в который я хочу добавить изображение. В основном мой код работал нормально, и база данных API, которую я использую, к сожалению, изменилась… Некоторые продукты в моей базе данных не имеют изображения, поэтому при вызове соответствующей строки выдается сообщение об ошибке… Итак, я хочу создать условие: если в базе данных есть изображение для рассматриваемого продукта, я хочу, чтобы оно отображалось
Источник изображения={{uri: URL item.photo.1.url}}
В противном случае я хочу, чтобы это был предустановленный логотип. <Источник изображения={require(‘../../../assets/images/logo.png’)}
Я сделал это так:
<ListItem.Content style={{flexDirection: 'row', justifyContent: 'space-between'}}>
{item.photo !== null amp;amp; item.photo > 0 ? (
<Image
source={{uri: URL item.photo._1_.url}}
style={{ width: 25, height: 25}}/>
) : (
<Image
source={require('../../../assets/images/logo.png')}
style={{ width: 25, height: 25}}
/>
)};
<ListItem.Title style={{width: '65%', fontSize: 16}}>{ ( item.name.length > 20 ) ? item.name.substring(0, 20) ' ...' : item.name}</ListItem.Title>
<ListItem.Subtitle style={{ color: '#F78400', position: "absolute", bottom: 0, right: 0 }}>{item.cost}{i18n.t("products.money")}</ListItem.Subtitle>
</ListItem.Content>
Но у меня есть 2 ошибки:
неопределенный не является объектом (оценка ‘item.photo.1.url’)
[Отклонение необработанного обещания: ошибка: текстовые строки должны отображаться внутри компонента.]
Чтобы показать вам, как выглядят данные :
И полный код этого экрана :
export default class Products extends Component {
constructor(props) {
super(props);
this.state = {
productId: (props.route.params amp;amp; props.route.params.productId ? props.route.params.productId : -1),
listData: '',
selectedId: '',
setSelectedId: '',
currentPage: 1,
loadMoreVisible: true,
loadMoreVisibleAtEnd: false,
displayArray: []
}
};
initListData = async () => {
let list = await getProducts(1);
if (list) {
this.setState({
displayArray: list,
loadMoreVisible: (list.length >= 10 ? true : false),
currentPage: 2
});
}
};
setNewData = async (page) => {
let list = await getProducts(parseInt(page));
if (list) {
this.setState({
displayArray: this.state.displayArray.concat(list),
loadMoreVisible: (list.length >= 10 ? true : false),
loadMoreVisibleAtEnd: false,
currentPage: parseInt(page) 1
});
}
};
loadMore() {
this.setNewData(this.state.currentPage);
}
displayBtnLoadMore() {
this.setState({
loadMoreVisibleAtEnd: true
});
}
async componentDidMount() {
this.initListData();
}
render() {
//console.log('url', URL );
//console.log('displayArray', this.state.displayArray);
//console.log('name', this.state.displayArray.name);
//console.log('photo', this.state.displayArray.photo);
return (
<View style={{flex: 1}}>
{this.state.displayArray !== null amp;amp; this.state.displayArray.length > 0 ? (
<View style={{ flex: 1}}>
<SafeAreaView>
<FlatList
data={this.state.displayArray}
extraData={this.selectedId}
style={{width: '98%'}}
onEndReached={() => this.displayBtnLoadMore()}
renderItem={({item, index, separators })=>
<View style={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
<ListItem
style={{width:'100%'}}
containerStyle= {{backgroundColor: index % 2 === 0 ? '#fde3a7' : '#FFF'}}
bottomDivider
onPress={() => this.props.navigation.navigate('ProductDetails', {productId:parseInt(item.id)})}>
<ListItem.Content style={{flexDirection: 'row', justifyContent: 'space-between'}}>
{item.photo !== null amp;amp; item.photo > 0 ? (
<Image
source={{uri: URL item.photo._1_.url}}
style={{ width: 25, height: 25}}/>
) : (
<Image
source={require('../../../assets/images/logo.png')}
style={{ width: 25, height: 25}}
/>
)};
<ListItem.Title style={{width: '65%', fontSize: 16}}>{ ( item.name.length > 20 ) ? item.name.substring(0, 20) ' ...' : item.name}</ListItem.Title>
<ListItem.Subtitle style={{ color: '#F78400', position: "absolute", bottom: 0, right: 0 }}>{item.cost}{i18n.t("products.money")}</ListItem.Subtitle>
</ListItem.Content>
</ListItem>
</View>
}
keyExtractor={(item,index)=>index.toString()}
style={{width:"100%"}}
/>
{this.state.loadMoreVisible === true amp;amp; this.state.loadMoreVisibleAtEnd === true ? (
<Button title=" " onPress={()=>{this.loadMore()}}></Button>
) : null
}
<View style={styles.container}>
<Text>{"n"}</Text>
<TouchableOpacity
style={styles.touchable2}
onPress={() => this.props.navigation.goBack()}
>
<View style={styles.container}>
<Button
color="#F78400"
title= 'Back'
onPress={() => this.props.navigation.goBack()}>BACK
</Button>
</View>
</TouchableOpacity>
</View>
<Text>{"nn"}</Text>
</SafeAreaView>
</View>
) : (
<View style={styles.container}>
<Text>{"nn" (this.state.displayArray === null ? i18n.t("products.searching") : i18n.t("products.nodata")) "nnn"}</Text>
<Button
color="#F78400"
title= 'Back'
onPress={() => this.props.navigation.goBack()}>BACK
</Button>
</View>
)}
</View>
);
};
}
Я немного запутался в том, как это сделать, поэтому, если у вас есть какие-либо подсказки, чтобы помочь мне, любая подсказка, это было бы здорово. Большое спасибо
Ответ №1:
Этот тест:
item.photo !== null amp;amp; item.photo > 0
Не вернет то, что вы ожидаете. Причина в том, что когда нет фотографии, свойство устанавливается в пустую строку. Итак, первая часть этого теста должна быть:
item.photo !== ''
Далее, когда есть фотография, photo
свойство является объектом. Итак, вторая часть должна быть:
item.photo.constructor === 'Object'
Но это будет усугубляться, если будет более одной фотографии. Ваш код предполагает, что вам нужна только первая фотография (независимо от того, сколько их может быть).
Поэтому, если вы внесете предложенные мной изменения, все должно работать так, как вы ожидаете.
На вашем месте я бы вообще пропустил первый тест, поскольку теперь в этом нет необходимости, поскольку второй тест охватывает оба случая. Я рекомендую просто сделать это:
{item.photo.constructor === 'Object' ? (
Комментарии:
1. Спасибо, и я понимаю ваши объяснения, спасибо, что нашли время разобраться и объяснить. Я тестирую и все еще получаю эту ошибку » [Отклонение необработанного обещания: ошибка: текстовые строки должны отображаться внутри компонента.] » Я не понимаю, я поставил условие не в том месте?
2. Я не вижу его здесь, но у вас где-то есть обычный текст в вашем возврате рендеринга. Я рекомендую вам удалить немного времени, чтобы посмотреть, сможете ли вы определить, где оно находится. Это может быть что-то столь же простое, как непечатаемый пробел (вы не можете видеть на экране). Но я ничего не вижу в этом коде.
3. Я думаю, что это мое первое условие, {this.state.displayArray !== null amp;amp; this.state.displayArray.length > 0 ? (……. Потому что, удалив его, он работает нормально… меня немного беспокоит его удаление, я включил его для безопасности, но, эй, может быть, я в конце концов удалю его, чтобы все было в порядке…
4. Ну, наконец, используя это: ‘{item.photo.constructor === ‘Object’ ? (‘ не сработало, но использование ‘ item.photo !== » ‘ само по себе работает нормально. Еще раз спасибо за вашу помощь. Я действительно благодарен