【问题标题】:Application gvies me a "Cannot read property" error, but only the layout is affected应用程序给我一个“无法读取属性”错误,但只有布局受到影响
【发布时间】:2021-05-25 05:24:26
【问题描述】:

对此我真的很摸不着头脑。

我正在制作一个 CRUD 应用程序,当我在编辑组件上工作时,这个问题就开始了。 我收到错误 Cannot read property 'id' of null 但!有趣的是,无论是在应用程序端还是在服务器端,数据实际上都会得到更新。 但是,该错误会影响布局。首先,删除按钮在模板中出现了两个位置而不是一个,并且当我更新时,主页并没有将我重定向到主页,而是主页在编辑页面上看起来像一个新的 div。我不知道发生了什么。

以下是不同的组件/组合:

详细信息组件:此处根据其 ID 存储有关特定文档的信息。

<template>
        <div v-if="playlist" class="playlist-details">
            <div class="playlist-info">
                <div class="cover">
                    <img :src="playlist.coverUrl">
                </div>
                <h2> {{ playlist.title }}</h2>
                <p> {{ playlist.description }} </p>
            </div>
        </div>
        <button @click="handleDelete">Delete</button>
        <EditSong :playlist="playlist" />
</template>

<script>
import EditSong from '../components/EditSong'
import useDocument from '../composables/useDocument'
import getDocument from '../composables/getDocument'
import useStorage from '../composables/useStorage'
import { useRouter } from "vue-router";
export default {
    props: ['id'],
    components: { EditSong },
    setup(props) {
        const { document: playlist } = getDocument('playlists', props.id)
        const { deleteDoc } = useDocument('playlists', props.id)
        const router = useRouter();
        const { deleteImage } = useStorage()

      const handleDelete = async () => {
          await deleteImage(playlist.value.filePath)
          await deleteDoc()
          confirm('Do you wish to delete this content?')
          router.push({ name: "Home" });
      }

        return {
            playlist,
            handleDelete
        }
    }
}
</script>

这里是 Edit 组件: 这是我在 Details 组件中编辑和更新数据的地方。这是我得到 TypeError 的地方。 它与 props.playlist.id 字段

有关
<template>
    <div class="edit-song">
      <form @submit.prevent="handleSubmit">
      <input type="text" required placeholder="title" v-model="title">
      <input type="text" required placeholder="description" v-model="description">
      <button v-if="!isPending">Update</button>
      <button v-else disabled>Updating...</button>
   </form>
    </div>
</template>

<script>
import { ref } from 'vue'
import { useRouter } from 'vue-router' 
import useDocument from '../composables/useDocument'
import useCollection from '../composables/useCollection'
export default {
    props: ['playlist'],
    setup(props) {
        const title = ref('')
        const description = ref('')
        const { updateDoc } = useDocument('playlists', props.playlist.id)
        const { error } = useCollection()
        const isPending = ref(false)
        const router = useRouter();

        const handleSubmit = async () => {
            await updateDoc({
                title: title.value,
                description: description.value,
            })
                isPending.value = false
                if(!error.value) {
                router.push({ name: "Home" })
             }
        }

        return {
            title,
            description,
            handleSubmit,
            isPending,
            error
        }
    }
}
</script>

最后,这是可组合的更新:,它存储更新函数

import { ref } from 'vue'
import { projectFirestore } from '../firebase/config'

const useDocument = (collection, id) => {
    const error = ref(null)
    const isPending = ref(false)

    let docRef = projectFirestore.collection(collection).doc(id)

    const updateDoc = async (updates) => {
        isPending.value = true
        error.value = null
        try {
            const res = await docRef.update(updates) 
            isPending.value = false
            return res
        }catch(err) {
            console.log(err.message)
            isPending.value = false
            error.value = 'Could not update document'
        }
    }

    return {
        error,
        isPending,
        updateDoc
    }

}

export default useDocument

【问题讨论】:

    标签: vue.js google-cloud-firestore vue-component crud vuejs3


    【解决方案1】:

    可能的情况是getDocument()document 返回一个refnull,它会异步更新:

    const getDocument = (collection, id) => {
      const document = ref(null)
    
      someAsyncFunc(() => {
        document.value = {...}
      })
    
      return {
        document
      }
    }
    

    由于document(重命名为playlist)绑定到EditSong 组件,它接收初始值(null)和异步填充的值,这会导致您的行为看到。

    一种解决方案是在playlist 上有条件地渲染EditSong

    <EditSong v-if="playlist" :playlist="playlist" />
    

    另一个是将updateDoc初始化移动到handleSubmit,并在那里添加null-check:

    const handleSubmit = async () => {
        if (!props.playlist) return
        const { updateDoc } = useDocument('playlists', props.playlist.id)
        await updateDoc(...)
    }
    

    【讨论】:

      猜你喜欢
      • 2023-01-25
      • 1970-01-01
      • 2020-04-30
      • 1970-01-01
      • 2019-04-27
      • 1970-01-01
      • 2020-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多