如果与过滤器一起使用,Pinia getter 未定义

问题描述 投票:0回答:1

我有一家 Pinia 商店:

import { defineStore } from "pinia";
import { api } from "@/services/api";

export const useMaterialStore = defineStore("material", {
  state: () => ({
    material: {},
  }),
  actions: {
    async load_material(machine_id) {
      const response = await api.get("material/machine/" + machine_id);
      console.log(response.data);
      this.material[machine_id] = response.data;
    },
  },
  getters: {
    getReadyMaterial: (state) => {
      return (machine_id) => state.material[machine_id];
    },
  },
});

load_material
操作从 API 获取对象数组并将其存储到状态。

状态看起来像这样:

{
    "2": [
        {
            "id": 1,
            "machine": 2,
            "order_date": null,
            "confirm_date": null,
            "delivery_date": null,
            "ready": false
        }
    ],
    "4": [
        {
            "id": 2,
            "machine": 4,
            "order_date": null,
            "confirm_date": null,
            "delivery_date": "2023-10-30",
            "ready": true
        },
        {
            "id": 3,
            "machine": 4,
            "order_date": null,
            "confirm_date": null,
            "delivery_date": null,
            "ready": false
        }
    ]
}

这是我的组件:

<template>
  <div>Ready: {{ materialStore.getReadyMaterial(props.machine_id) }}</div>
</template>

<script setup>
import { onMounted } from "vue";
import { useMaterialStore } from "@/store/material";

const materialStore = useMaterialStore();

const props = defineProps({
  machine_id: Number,
});

onMounted(() => {
  materialStore.load_material(props.machine_id);
});
</script>

所有这些都按预期工作,如果

props.machine_id
2
,则 div 看起来像这样:

[ { "id": 1, "machine": 2, "order_date": null, "confirm_date": null, "delivery_date": null, "ready": false } ]

不,问题来了,我想过滤数组中

ready
设置为
true
的对象。

如果我将 getter 更改为

return (machine_id) => state.material[machine_id].filter((m) => m.ready == true);
,我会在控制台中收到错误:

Uncaught (in promise) TypeError: state.material[machine_id] is undefined

我完全迷失了这里发生的事情,希望有人能指出我做错了什么

filter vuejs3 getter pinia
1个回答
0
投票

您的 getter 会立即运行,不会等待您的状态加载。在第一个示例中,

state.material[machine_id]
最初是未定义的。当你的数据被获取时,你的 UI 实际上正在渲染
{{ undefined }}
,这在语法上是合法的,但什么也不渲染。数据稍后到达并按预期呈现。这一切之所以有效,是因为除了归还它之外,您没有尝试对
undefined
做任何事情。

在第二个示例中,

state.material[machine_id]
最初仍然是未定义的,但现在您尝试在其上调用
filter()
,这会给您带来错误。在您所在的州确实有可用于过滤的数据之前,您无法执行此操作。

一种解决方案是在

materialStore.material
数据存在之前不要调用 getter。这可以通过 div 上的
v-if
来完成,检查对象是否为空。只有当它非空时,它才会尝试渲染,这将调用你的 getter,此时这样做是安全的:

<div v-if="Object.keys(materialStore.material).length > 0">
  Ready: {{ materialStore.getReadyMaterial(props.machine_id) }}
</div>
© www.soinside.com 2019 - 2024. All rights reserved.