所以我正在尝试为我的网站构建一个新闻提要阅读器。它非常基本,只有 2 个平面列表。一个垂直列出文章,另一个水平列出网站。单击水平项目时,它会更新 2 个不同的状态设置。这 2 个设置被设置为 flatLists 的 extraData。按下后水平的会重新渲染,但垂直的不会。
onPress 正在更新站点和 selectedId 状态,当站点 flatList 重新呈现并显示背景颜色更改时,artile flatList 不会使用新提要重新呈现。
这是代码。
import { StatusBar } from 'expo-status-bar';
import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, Image, View, FlatList, TouchableOpacity, Avatar, Dimensions } from 'react-native';
import Header from './components/header';
import Article from './components/article';
export default function App() {
const [isLoading, setLoading] = useState(true);
const [articles, setArticles] = useState([]);
const [site, setSite] = useState('https://minedhash.com/feed');
useEffect(() => {
fetch('https://api.rss2json.com/v1/api.json?rss_url='+site)
.then((response) => response.json())
.then((json) => setArticles(json.items))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
const [selectedId, setSelectedId] = useState(2);
const nftImg = require('assets/NFT.png');
const mhImg = require('assets/MH.png');
const cntImg = require('assets/CNT.png');
const sntImg = require('assets/SNT.png');
const entImg = require('assets/ENT.png');
const bscImg = require('assets/BSC.png');
const ethImg = require('assets/ETH.png');
const fafImg = require('assets/FAF.png');
const pntImg = require('assets/PNT.png');
const cenImg = require('assets/CEN.png');
const siteList = [
{'id': 1, 'name': 'NFT News Today', 'avatar': nftImg, 'color': '#ffffff', 'bgcolor': '#6856dd', 'url': 'https://nftnewstoday.com/feed'},
{'id': 2, 'name': 'Mined Hash', 'avatar': mhImg, 'color': '#000000', 'bgcolor': '#ff5757', 'url': 'https://minedhash.com/feed'},
{'id': 3, 'name': 'Cardano News Today', 'avatar': cntImg, 'color': '#000000', 'bgcolor': '#3cc8c8', 'url': 'https://cardanonewstoday.com/feed'},
{'id': 4, 'name': 'Solana News Today', 'avatar': sntImg, 'color': '#000000', 'bgcolor': '#7783d4', 'url': 'https://solananewstoday.com/feed'},
{'id': 5, 'name': 'Elrond News Today', 'avatar': entImg, 'color': '#ffffff', 'bgcolor': '#090223', 'url': 'https://elrondnews.com/feed'},
{'id': 6, 'name': 'BSC Chain', 'avatar': bscImg, 'color': '#ffffff', 'bgcolor': '#2b2e35', 'url': 'https://bscchainnews.com/feed'},
{'id': 7, 'name': 'Ethereum News Today', 'avatar': ethImg, 'color': '#000000', 'bgcolor': '#d8cd51', 'url': 'https://ethereumnewstoday.net/feed'},
{'id': 8, 'name': 'Finance and Freedom', 'avatar': fafImg, 'color': '#ffffff', 'bgcolor': '#0000fe', 'url': 'https://financeandfreedom.org/feed'},
{'id': 9, 'name': 'Polkadat News Today', 'avatar': pntImg, 'color': '#ffffff', 'bgcolor': '#1e1e1e', 'url': 'https://polkadotnewstoday.com/feed'},
{'id': 10, 'name': 'Crypto Exchange News Today', 'avatar': cenImg, 'color': '#ffffff', 'bgcolor': '#0277bd', 'url': 'https://cryptoexchangenews.net/feed'},
]
const Item = ({ item, onPress, backgroundColor, textColor }) => (
<TouchableOpacity onPress={onPress} style={[styles.site, backgroundColor]}>
<Image style={styles.tinyLogo} source={item.avatar} resizeMode='cover' />
<Text style={[styles.title, textColor]}>{item.name}</Text>
</TouchableOpacity>
);
const renderItem = ({ item }) => {
const backgroundColor = item.id == selectedId ? "#373361" : "#05003a";
const color = 'white';
return (
<Item
item={item}
onPress={function(){
setSelectedId(item.id);
setSite(item.url);
}}
backgroundColor={{ backgroundColor }}
textColor={{ color }}
/>
);
};
return (
<View style={styles.container}>
{/* header */}
<Header />
<View style={styles.content}>
<View style={styles.articleList}>
{/* Content */}
{isLoading ? <Text>Loading...</Text> :
( <FlatList
data={articles}
renderItem={({ item }) => (
<Article item={item}/>
)}
keyExtractor={(item, index) => index.toString()}
extraData={site}
/>
)}
</View>
</View>
<View style={styles.siteBar}>
{/* siteBar */}
<FlatList
horizontal
data={siteList}
renderItem={renderItem}
keyExtractor={(item) => item.id.toString()}
extraData={selectedId}
/>
</View>
<StatusBar style='light' />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
content: {
paddingLeft: 20,
paddingRight: 20,
},
articleList: {
marginTop: 10,
marginBottom: 10,
height: Dimensions.get('window').height - 190
},
siteBar: {
height: 140,
width: Dimensions.get('window').width,
backgroundColor: '#fff',
},
site: {
height: 200,
width: 110,
marginLeft: 5,
padding: 5,
borderColor: '#fff',
borderWidth: 1,
borderRadius: 10,
textAlign: 'center',
},
title: {
textAlign: 'center',
},
tinyLogo: {
height: 90,
width: 90,
marginLeft: 5,
marginTop: 5
}
});