Zeyad Shaban
Zeyad Shaban

Reputation: 1016

React State giving undefined, new to react

I'm new to react-native, I have been working on a simple app but for some reason I keep getting (undefined) for some of my states, also when fetching data the server is getting called multiple times with value (undefined) before returning an actual value. I have been searching for quite long but didn't find anything that helped so I came here to ask for help from more advance React developers than me.

my code looks like this:

const { data: chat, loading } = useApi(chatApi.getChat, { chatId: chatId, channelId: route.params.channelId });
const chatMessages = chat.messages  // I declared this only for testing
const [messages, setMessages] = useState(chatMessages);
console.log("Chat Messages: " + chatMessages)
console.log("messages State: " + messages)

In the terminal I get:

Chat Messages: undefined
messages State: undefined
Chat Messages: undefined
messages State: undefined
Chat Messages: [object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
messages State: undefined

Also, why does the 'chat' variable is being rendered multiple times with value (undefined) before giving an actual value? This caused the backend WS server to be called multiple times with no reason causing worse performance

useApi hook:

import { useEffect, useState } from "react";

const useApi = (apiFunc, funcParams ={}) => {
    const [data, setData] = useState([]);
    const [error, setError] = useState(false);
    const [loading, setLoading] = useState(false);

    const fetchData = async () => {
        setLoading(true);
        const response = await apiFunc(funcParams);
        setLoading(false);
        if (!response.ok) return setError(true);
        setData(response.data);
    };
    useEffect(() => { fetchData() }, []);
    if (data) return { data, setData, error, loading, setLoading };
};

export default useApi;

full code

:
const chatId = route.params.chat.id;
    const { data: chat, loading } = useApi(chatApi.getChat, { chatId: chatId, channelId: route.params.channelId });
    const { user } = useAuth();
    const [text, setText] = useState(() => { return ""; });
    const chatMessages = chat.messages  // I declared this only for testing
    const [messages, setMessages] = useState(chatMessages);
    console.log("Chat Messages: " + chatMessages)
    console.log("messages State: " + messages)

    const chatSocket = new WebSocket(`${settings.wsUrl}chat/${chatId}/?userId=${user.id}`);
    

    // Join & Leave Room
    useEffect(() => {
        chatSocket.onmessage = e => {
            const data = JSON.parse(e.data);
            setMessages([...messages, data.message]);
        };
        return () => {
            chatSocket.close(0);
        };
    }, []);

    const handleSendMessage = () => {
        chatSocket.send(JSON.stringify({
            text: text,
        }));
        setText("");
    };

    return (
        <>
            ...
        </>

Upvotes: 0

Views: 995

Answers (1)

Alfred-Mountfield
Alfred-Mountfield

Reputation: 71

It looks like you're getting undefined while the data is loading (as the data isn't there yet and it's therefore undefined), you're printing the value of the variable whenever the component renders regardless of if the data has loaded yet.

You have access to a loading indicator: const { data: chat, loading } but you're not using the loading variable for anything conditional. Something like

if (!loading && data != null) {
   console.log("Chat Messages: " + chatMessages)
   console.log("messages State: " + messages)
   const chatSocket = new WebSocket(`${settings.wsUrl}chat/${chatId}/?userId=${user.id}`);
}

Upvotes: 1

Related Questions