【问题标题】:useEffect and useState not setting value in fetchuseEffect 和 useState 未在 fetch 中设置值
【发布时间】:2020-07-24 12:38:47
【问题描述】:

我有一个杂志风格的应用程序,它有一个索引页面 - 名为 HomeScreen 的组件 - (带有文章列表)和一个详细页面 - 名为 Details 的组件 - (带有完整文章); 在它们上面我有一个 Home 组件,它是 bot 的 Stack 导航。

首页组件

 const Home = ({}) => {
  return (
    <Stack.Navigator initialRouteName="Home">
      <Stack.Screen name="Home" component={HomeScreen} options={HeaderOption} />
      <Stack.Screen
        name="Details"
        component={DetailsScreen}
        options={HeaderOption}
      />
    </Stack.Navigator>
  );
};
export default Home;

然后(同一个文件)获得 HomeScreen 组件,该组件(正确)呈现文章列表,它使用 useEffect 从 API 获取它们

function HomeScreen({ navigation }) {
  const [article, setArticles] = useState();
  const [loadingArticle, setLoading] = useState(false);
  useEffect(() => {
    console.log('start Fetching');
    fetchTitles();
  }, []);
const fetchTitles = () => {
    fetch('myURL', {
      method: 'GET',
    })
      .then((response) => response.json())

      .then((responseData) => {
        setArticles(responseData);
      })
      .finally(() => setLoading(false));
  };

  const { state } = useContext(AuthContext);
return (
    <View
      style={{
        flex: 1,
        paddingTop: Constants.HEIGTH,
        backgroundColor: Constants.MAIN_GREEN,
      }}
    >
      <LogoHeader title="TITOLO APP" isHome={true} navigation={navigation} />
      <View style={{ ...styles.container }}>
        <FlatList
          data={article}
          keyExtractor={(item) => item.id.toString()}
          renderItem={({ item }) => (
            <TouchableOpacity
              onPress={() =>
                navigation.navigate('Details', {
                  itemId: item.id,
                })
              }
            >
              <Card>
                <Card.Content>
                  <HTML
                    html={item.title.rendered}
                    baseFontStyle={{ fontSize: 20, color: '#adadad' }}
                  />

                  <Paragraph>
                    Published on {moment(item.date).format('LL')}
                  </Paragraph>
                </Card.Content>
                <Card.Cover source={{ uri: item.jetpack_featured_media_url }} />
                <Card.Content>
                  <HTML
                    html={item.excerpt.rendered}
                    imagesMaxWidth={Dimensions.get('window').width}
                  />
                </Card.Content>
              </Card>
            </TouchableOpacity>
          )}
        />
      </View>
    </View>
  );
}

当我点击文章时,我使用正确传递的 id 正确到达 Details,但 singleArticle 为“null”,即使 responseData 正确:

 function DetailsScreen({ route, navigation }) {
      const { state } = useContext(AuthContext);
      const [singleArticle, setSingleArticle] = useState(null);
      const [loadingArticle, setLoadingSingle] = useState(false);
      useEffect(() => {
       setLoadingSingle(true);
       console.log(loadingArticle); //return false (???)
        fetchSingle();
      }, []);
    
      const fetchSingle = () => {
        console.log('get_single');
        fetch(
          'myURLgetsingle?' +
            route.params.itemId,
    
          {
            method: 'GET',
          }
        )
          .then((response) => response.json())
    
          .then((responseData) => {
            console.log('setting');
    
            console.log(responseData); //return the values i need
            setSingleArticle(responseData);
            console.log(singleArticle); //return null
          })
          .finally(() => setLoadingSingle(false));
      };
    
      console.log(singleArticle.title.rendered);
      return (
        <View
          style={{
            flex: 1,
            paddingTop: Constants.HEIGTH,
            backgroundColor: Constants.MAIN_GREEN,
          }}
        >
          <LogoHeader title="" isHome={false} navigation={navigation} />
          <Card style={{ ...styles.container, padding: 10 }}>
            <Card.Content>
              <Title>{singleArticle.title.rendered}</Title>
              <Paragraph></Paragraph>
            </Card.Content>
          </Card>
        </View>
      );
    }

我想我错过了 react native 的一些基本用法,有什么办法可以修复它吗? 谢谢

【问题讨论】:

    标签: react-native fetch


    【解决方案1】:

    Ciao,这对于 Hooks 来说是完全正常的。当您调用setSingleArticle(responseData); 时,如果您尝试在下一行记录singleArticle,则可以肯定您获得了null 值。发生这种情况是因为 setSingleArticle 是异步的,并且在 Hooks 中,您没有如下回调:

    setSingleArticle(responseData, () => {
      // here I'm sure that singleArticle was setted
      // with Hooks this is impossible to do!
    });
    

    所以结果是,在这一行console.log(singleArticle.title.rendered); 中,您应该收到类似“无法获取 null 属性标题”的错误。由于您的singleArticle 值来自获取,您可以尝试修改singleArticle 默认值,如:

    const [singleArticle, setSingleArticle] = useState({title: {rendered: ''}});
    

    有了这个初始化console.log(singleArticle.title.rendered); 不会失败。这条线同样的事情&lt;Title&gt;{singleArticle.title.rendered}&lt;/Title&gt;

    编辑

    对于正在加载的样式,您可以这样做:

    <Title>{singleArticle.title.rendered === '' ? "Loading..." : singleArticle.title.rendered}</Title>
    

    【讨论】:

    • useState 集合是异步的,这很好,但是在主页(我得到文章列表的地方)它们总是没有错过,而且如果它们是异步的,我怎么能我真的很喜欢 useState 的加载方式吗?您的建议看起来不错并消除了错误,但详细信息页面上的磁贴仍然为空
    • 如果我没看错你想隐藏&lt;Title&gt;{singleArticle.title.rendered}&lt;/Title&gt; 显示例如“正在加载...”,直到设置singleArticle,对吗?抱歉,英语不是我的母语...
    • 类似的东西以及 singleArticle 对象的所有其余部分,我尝试按照您的方法进行操作,当然它不再显示错误,但标题从未填充。 Details 组件是 HomeScreen 的副本,但 HomeScreen 永远不会失败。另外,如果在我的设备上,我在详细信息屏幕上并从代码编辑器中保存文件,似乎 useState 有效,它就像它只第一次有效(因此,如果我在 HomeScreen 上加载列表,但后续调用不起作用)
    • Ciao,这很奇怪(我的意思是当你说从不填充时)。最初是无效的(因为初始化),但是当 fetch 返回值并且您调用 setSingleArticle(responseData) ract 时,应该使用正确的值重新渲染 。你能告诉我 console.log(responseData) 的输出吗?
    • 是的,内容对象以 void 开头,加载对象以 true 开头,i fetch(并且它获取!)使用 responseData 对象设置内容对象,并在我使用的 fetch 结束时设置。 finally(() => { setLoadingSingle(false); //console.log(singleArticle); //console.log(loadingSingleArticle); });
    猜你喜欢
    • 2020-11-02
    • 2020-02-14
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    • 1970-01-01
    • 2020-03-08
    • 2021-04-10
    • 1970-01-01
    相关资源
    最近更新 更多