setState не сохраняет состояние вне области действия функции - PullRequest
1 голос
/ 16 июня 2020

функция listFilesAndDirectories из справочника API хранилища firebase - это то, что я использую для получения URL-адреса загрузки для моих изображений, уже сохраненных в ведре хранилища, но использую setState для сохранения состояния в качестве URL-адреса до передачи, поскольку URI изображения не работает

import React, {setState} from 'react';
import {DrawerActions, useNavigation} from '@react-navigation/native';

const Gallery: () => React$Node = () => {
  const navigation = useNavigation();

  function listFilesAndDirectories(reference, pageToken) {
    return reference.list({pageToken}).then(result => {
      result.items.forEach(ref => {
        // call getDownloadURL on every object reference
        ref.getDownloadURL().then(url => {
          setState({url: url});
          console.log(
            `File is referenced from :\n ${storageReference}:\n\n Image URL is:\n ${url}`,
          );
          console.log(`url is available here ${url}`);
           //after this point URL is no longer available
        });
      });

      if (result.nextPageToken) {
        return listFilesAndDirectories(reference, result.nextPageToken);
      }

      return Promise.resolve();
    });
  }

  const storageReference = firebase
    .storage()
    .refFromURL('gs://app404.com/images');

  listFilesAndDirectories(storageReference).then(() => {
    console.log('Started listing image download urls');
  });

  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView>
        <View style={SharedStyles.header}>
          <TouchableOpacity
            onPress={() => {
              navigation.dispatch(DrawerActions.openDrawer());
            }}>
            <Hamburg />
          </TouchableOpacity>
          <Header title="Gallery" />
        </View>
        <ScrollView contentInsetAdjustmentBehavior="automatic">
          <View style={styles.container}>
            <View style={styles.sectionContainer}>
              <View>
                <Text>
                  Welcome to the Abulad Gallery! Come back for more content....
                </Text>
                <Image
                  source={{
                    uri: {url}//url is not defined
                  }}
                  style={styles.fetchedImage}
                />
              </View>
            </View>
          </View>
        </ScrollView>
      </SafeAreaView>
    </>
  );
};

необходим способ сохранить состояние даже вне функции, чтобы изображение могло отображаться. Спасибо

1 Ответ

0 голосов
/ 16 июня 2020

Вы пытаетесь использовать хуки, не используя их правильно. useState - это функция инициализации в React, она по существу создает начальное состояние и создает ссылку в стеке выполнения React, что при вызове возвращенной функции set* узел должен повторно отрисоваться.

Это вот как вы используете useState:

import { useState} from "react";

const Gallery: () => {
  const navigation = useNavigation();
  const [ downloadUrl, setDownloadUrl ] = useState({ url: undefined });
  console.log(downloadUrl);
  // should be {url: undefined} on 1st render, {url: <some url>} on subsequent renders

  // This should be refactored to `useEffect` to take advantage of async operations in React
  function listFilesAndDirectories(reference, pageToken) {
    return reference.list({pageToken}).then(result => {
      result.items.forEach(ref => {
        // call getDownloadURL on every object reference
        ref.getDownloadURL().then(url => {
          // An array would be better here, but this is just for example
          setDownloadUrl({ url }); // creates obj {url: url}, will cause a re-render once execution is complete
          console.log(
            `File is referenced from :\n ${storageReference}:\n\n Image URL is:\n ${url}`,
          );
          console.log(`url is available here ${url}`);
           //after this point URL is no longer available
        });
      });

      if (result.nextPageToken) {
        return listFilesAndDirectories(reference, result.nextPageToken);
      }

      return Promise.resolve();
    });
  }

  // ...

  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView>
        <View style={SharedStyles.header}>
          <TouchableOpacity
            onPress={() => {
              navigation.dispatch(DrawerActions.openDrawer());
            }}>
            <Hamburg />
          </TouchableOpacity>
          <Header title="Gallery" />
        </View>
        <ScrollView contentInsetAdjustmentBehavior="automatic">
          <View style={styles.container}>
            <View style={styles.sectionContainer}>
              <View>
                <Text>
                  Welcome to the Abulad Gallery! Come back for more content....
                </Text>
                <Image
                  source={{
                    uri: { downloadUrl.url }//url is not defined
                  }}
                  style={styles.fetchedImage}
                />
              </View>
            </View>
          </View>
        </ScrollView>
      </SafeAreaView>
    </>
  );
}

После того, как вы это заработаете, вы можете обновить заполнитель изображения, чтобы использовать значок счетчика или какой-либо другой значок загрузки, например

{ !downloadUrl.url ? <Spinner /> : (
  <div>...</div>
)}
...