I’m trying to update a chain of components from side class by passing a callback to function with a ref variable update (component with a class to listen to websocket).
After the callback is called, i receive an warning Invalid prop: type check failed for prop "teamInfo". Expected Object, got Undefined
and all of child components are failed because of undefined data was passed into them.
I tried to update ref from same component by making a button and calling a function that will do the same thing as a class with callback, but the data is successfully updated.
Minimal code sample to test:
<script setup lang="ts">
import { ref } from "vue";
import {HubConnectionBuilder} from "@microsoft/signalr";
enum DecryptoTeam {
Unknown = 0,
Red = 1,
Blue = 2
}
interface DecryptoMatchFake {
round: number;
teams: { [key in DecryptoTeam]: TeamFake };
}
interface TeamFake {
players: { [key: string]: string };
}
let loading = ref<boolean>(true);
let matchInfo = ref<DecryptoMatchFake | null>(null);
const props = defineProps<{ id: string }>();
const connection = new HubConnectionBuilder()
.withUrl("/api/decryptoMessageHub")
.withAutomaticReconnect()
.build();
function start() {
try {
connection.start().then(() => {
connection.invoke("JoinMatch", props.id);
connection.on("StateChanged", (match: DecryptoMatchFake) => {
matchInfo.value = match;
loading.value = false;
});
});
} catch (err) {
console.error(err);
setTimeout(start, 5000);
}
}
start();
</script>
<template>
<div v-if="loading" class="title">
Loading match data...
</div>
<div v-if="matchInfo" class="content">
<p class="title">Round #{{matchInfo.round}}</p>
<div class="split">
<div class="team">
<div class="block-center">
<p v-for="player in matchInfo.teams[DecryptoTeam.Blue].players">{{player}}</p>
</div>
</div>
</div>
</div>
</template>
Full source code is available here.
8
In your TeamInfo.vue
file you are updating matchInfo
onMounted
but this lifecycle hook is only called after the template
has already compiled (see vue lifecycle hooks).
the onMounted hook can be used to run code after the component has finished the initial rendering and created the DOM nodes
Your components are being passed props which are still null
. I would try moving your DecryptoDataService.getMatch(props.id)
promise into script setup
– that way it gets run during setup rather than after the template is compiled. You’ll probably be good to just completely remove the onMounted
hook.
2
I found the issue. It was a matter of a wrong serialization of dictionary keys on a backend side. I fixed it with a custom serializer for a dictionary keys, but haven’t thought that SignalR will have the same problem.
Before:
{... teams: {'Blue': {}, 'Red': {}} }
After:
{... teams: {1: {}, 2: {}} }
0