简体   繁体   中英

React hooks array passing in number when passed into props of component

I am currently working on a chat application and for some reason every time I pass in my array of messages as a prop to another component it passes in a number to the component instead of the message object. I have tried a lot of different methods of passing it in regarding using multiple components etc but it seems to still be passing in the number of elements for some reason. Any help is appreciated... code is below

Component receiving the props

import React, { useEffect } from 'react'
import Message from '../../Message/Message'

function Messages({ messages }) {
    useEffect(() => {
        console.log(messages)
    }, [messages])
    return (
        <div>
            test
        </div>
    )
}

export default Messages
// Import React dependencies.
import React, { useEffect, useState, } from "react";
// Import React dependencies.
import io from 'socket.io-client'
import axios from 'axios'
import Messages from './Messages/Messages'
import uuid from 'react-uuid'
import { Redirect } from 'react-router-dom'
// Import the Slate components and React plugin.
const ENDPOINT = 'http://localhost:5000/'
export const socket = io.connect(ENDPOINT)




const LiveChatFunction = ({ group_id }) => {
    // Add the initial value when setting up our state.
    const [message, setValue] = useState("")
    const [user, setUser] = useState("")
    const [groupId, setGroup] = useState('')
    const [messages, setMessages] = useState([])
    const [toLogin, userAuth] = useState(false)
    useEffect(() => {

        setGroup(group_id)
        axios.post('http://localhost:5000/api/users/refresh_token', null, { withCredentials: true }).then(data => {
            if (!data.data.accessToken) {
                userAuth(true)
            }
        })
        axios.get('http://localhost:5000/api/users/userInfo', { withCredentials: true }).then(data => {
            setUser(data.data.user)
        })
        socket.on(`message-${group_id}`, data => {
            setMessages(messages.push(data))
        });

        axios.get(`http://localhost:5000/live/${group_id}`).then(x => {
            console.log(x.data)
        })
    }, [group_id, messages])

    function setClick() {
        const data = {
            messageId: uuid(),
            user,
            groupId,
            message
        }
        socket.emit('message', data)
    }

    if (toLogin) {
        return (
            <Redirect to="/login" />
        )
    }
    return (
        <div>
            <input placeholder="message" type="text" onChange={value => {
                setValue(value.target.value)
                socket.emit('typing-message', { username: user, time: new Date() })
            }} />
            <button onClick={setClick}>Submit</button>
            <Messages messages={messages} />
        </div>

    )
}

export default LiveChatFunction;

I have added some comments of what I think you can change:

useEffect(() => {
  const recieveFunction = (data) => {
    //using callback so no dependency on messages
    setMessages((messages) => messages.push(data));
  };
  async function init() {
    //next line is pointless, this runs when group_id
    // has changed so something must have set it
    // setGroup(group_id);
    await axios //not sure if this should be done before listening to socket
      .post(
        'http://localhost:5000/api/users/refresh_token',
        null,
        { withCredentials: true }
      )
      .then((data) => {
        if (!data.data.accessToken) {
          userAuth(true);
        }
      });
    await axios
      .get('http://localhost:5000/api/users/userInfo', {
        withCredentials: true,
      })
      .then((data) => {
        setUser(data.data.user);
      });
    //start listening to socket after user info is set
    socket.on(`message-${group_id}`, recieveFunction);

    axios
      .get(`http://localhost:5000/live/${group_id}`)
      .then((x) => {
        console.log(x.data);
      });
  }
  init();
  //returning cleanup function, guessing socket.off exists
  return () =>
    socket.off(`message-${group_id}`, recieveFunction);
}, [group_id]); //no messages dependencies
console.log('messages are now:',messages);

If messages is still not set correctly then can you log it

So I think I found your problem:

In your useEffect hook, you're setting messages to the wrong thing.

socket.on(`message-${group_id}`, data => {
    setMessages(messages.push(data))
});

An example:

const m = [].push();
console.log(m);
// m === 0
const n = [].push({});
console.log(n);
// n === 1

As you can see this is the index.

So what you need is:

socket.on(`message-${group_id}`, data => {
    messages.push(data);
    setMessages(messages);
});

This will set messages to the array of messages.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM