1

所以我正在尝试为我的网站构建一个新闻提要阅读器。它非常基本,只有 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
  }
});
4

1 回答 1

2

根据代码观察,我可以看到 useEffect 代码中可能存在依赖问题。

通过在 useEffect 依赖项列表中添加站点依赖项来尝试。

试试前。

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))
  }, [site])

代替

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))
  }, [])
于 2021-07-02T10:59:26.683 回答