UI 中的图像在使用 State Hooks 时不会更新

Image in UI doesn't update when using State Hooks

我有一个状态钩子变量定义如下:

const [imageURL, setimageURL] = useState(null);

我正在使用 expo-image-picker 从我的图库中获取图像并将其上传到 firebase 存储。然后我得到这张图片的 URL 并相应地更新 imageURL 的值。

const pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
        mediaTypes: ImagePicker.MediaTypeOptions.Images,
        allowsEditing: true,
        aspect: [4, 3],
        quality: 1,
    });

    console.log(result);

    if (!result.cancelled) {
        uploadImage(result.uri, 'Profile-picture')
            .then(() => {
                console.log('it work')
            })
            .catch(error => {
                console.log('it does not work')
                console.error(error)
            })
            
    }       
}   

const uploadImage = async (uri, imageName) => {
    const user = firebase.auth().currentUser
    const currentUser = user.uid
    const response = await fetch(uri)
    const blob = await response.blob()

    const ref = firebase.storage().ref(currentUser + '/profilePicture/' + imageName)
    ref.put(blob)
    ref.getDownloadURL()
        .then((url) => {
            setimageURL(url)
            setLocalStorage(url)
        })
}

当页面首次加载时,该值为空,因此有一个空白图标。上传图片并获得 URL 后,我的应用程序上的 UI 不会更新以显示新图片。除非我上传另一张新图片,否则它将保持空白。一旦发生这种情况,UI 将更新,但它现在将显示我第一次上传的图像。关于我可能做错了什么的任何想法?

注意:我什至尝试添加一个文本组件并传入 imageURL 变量以显示当前 URL,由于某种原因,此文本会正确更新,但图像不会。 (此处未显示)

 return (
    <View style={styles.container}>
        <KeyboardAwareScrollView
            style={{ flex: 1, width: '100%' }}
            keyboardShouldPersistTaps="always">
        <Avatar
            size="xlarge" 
            rounded
            source={{
                uri: imageURL
            }}
            icon={{ name: 'user', type: 'font-awesome' }}
            activeOpacity={0.7}
            containerStyle={{alignSelf: 'center', backgroundColor: '#89CFF0', marginTop: 50}}
        >
        </Avatar>

发生这种情况是因为您在子组件中使用了图像源。 使用 imageURL 的初始状态 null 构造子组件。 当父组件中的状态更新时,子组件即 <Avatar> 不知道此更新并且不会重新呈现。不建议将初始状态值传递给子组件。但如果你不能避免它,这里有一个技巧。 将密钥添加到您的 Avatar 组件

const [imageKey, setimageKey] = useState(1);
<Avatar 
  size="xlarge" 
  rounded 
  source={{ uri: imageURL }} 
  icon={{ name: 'user', type: 'font-awesome' }} 
  activeOpacity={0.7} 
  containerStyle={{alignSelf: 'center', backgroundColor: '#89CFF0', 
  marginTop: 50}} 
  key={imageKey}
> </Avatar>

并在每次获取新的 imageUrl 时更新密钥:

const uploadImage = async (uri, imageName) => { 
  const user = firebase.auth().currentUser 
  const currentUser = user.uid const response = await fetch(uri) 
  const blob = await response.blob() 
  const ref = firebase.storage().ref(currentUser + '/profilePicture/' 
        + imageName) ref.put(blob) ref.getDownloadURL() 
  .then((url) => { 
    setimageURL(url) 
    setLocalStorage(url) 
    setimageKey(prev => prev +1)
  }
 ) 
}