Strange react-native state behaviour while using socket io

删除回忆录丶 提交于 2020-12-26 05:02:20

问题


Hi currently im trying to create a simple group chat apps. when i use this on useEffect

useEffect(() => {
    // i want to fetch data from the backend first and concat it with the msg that will be send during the chat
    handleGetGroupMessage();
    let socket = io(socketUrl);
    socket.on("GroupChat", (msg) => {
      console.log("this is the chat messages", chatMessages);
      setChatMessages(chatMessages.concat(msg));
    });
  }, []);

when the apps is loaded all the messages from my backend was stored in that state. but when i send a new message all the array was replaced with chat object. so i console.log the chatMessages state and it was an empty array. what i want is to concat previous state with the msg object

note : chatMessages state is an array of object

here's my full conde

import React, { useEffect, useState, useContext } from "react";
import {
  View,
  StyleSheet,
  SafeAreaView,
  FlatList,
  Text,
  TouchableHighlight,
  Keyboard,
} from "react-native";
import { LinearGradient } from "expo-linear-gradient";
import Constants from "expo-constants";
import colors from "../config/colors";
import { TextInput } from "react-native-gesture-handler";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { sendMessage, getGroupMessage } from "../api/chatApi";
import io from "socket.io-client";
import AuthContext from "../auth/AuthContext";
import { socketUrl } from "../config/url";
import axios from "axios";
import { apiUrl } from "../config/url";

const GroupChatScreen = (props) => {
  const authContext = useContext(AuthContext);
  const [chatMessages, setChatMessages] = useState([]);
  const [chat, setChat] = useState(null);
  const handleSendMessage = async (chat) => {
    const result = await sendMessage({ chat }, authContext.token);
    setChat(null);
    Keyboard.dismiss();
    let socket = io(socketUrl);
    socket.emit("GroupChat", result);
  };
  const handleGetGroupMessage = () => {
    axios
      .get(`${apiUrl}/messages/group`, {
        headers: { token: authContext.token },
      })
      .then((data) => {
        setChatMessages(data.data);
      })
      .catch((error) => {
        console.log(error);
      });
  };

  useEffect(() => {
    // i want to fetch data from the backend first and concat it with the msg that will be send
    console.log(authContext.userData, "userdata");
    handleGetGroupMessage();
    let socket = io(socketUrl);
    socket.on("GroupChat", (msg) => {
      console.log("this is the chat messages", chatMessages);
      setChatMessages(chatMessages.concat(msg));
    });
  }, []);

  return (
    <LinearGradient
      colors={[colors.BLUE, colors.DARKBLUE]}
      style={styles.container}
    >
      <View style={styles.chatTitleContainer}>
        <Text style={styles.chatTitle}>Pub Chat</Text>
      </View>
      <FlatList
        style={styles.flatList}
        keyExtractor={(item) => item.ChatId.toString()}
        data={chatMessages}
        renderItem={({ item }) => {
          if (item.from === authContext.userData.id) {
            return (
              <View style={styles.fromMe}>
                <View style={styles.myChatContainer}>
                  <Text style={styles.myChat}>{item.chat}</Text>
                </View>
              </View>
            );
          } else {
            return (
              <View style={styles.fromYou}>
                <Text style={styles.yourUsername}>{item.username}</Text>
                <View style={styles.yourChatContainer}>
                  <Text style={styles.yourChat}>{item.chat}</Text>
                </View>
              </View>
            );
          }
        }}
      ></FlatList>
      <View style={styles.textInputContainer}>
        <TextInput
          onChangeText={(text) => setChat(text)}
          style={styles.textInput}
          value={chat}
          placeholder="Enter Chat Here"
        />
        <TouchableHighlight
          onPress={() => handleSendMessage(chat)}
          style={styles.roundButton}
        >
          <MaterialCommunityIcons
            name="send"
            color="white"
            size={30}
            style={styles.roundButtonIcon}
          />
        </TouchableHighlight>
      </View>
    </LinearGradient>
  );
};

export default GroupChatScreen;
const styles = StyleSheet.create({
  chatTitle: {
    fontSize: 20,
    padding: 10,
    color: "white",
    textAlign: "center",
  },
  chatTitleContainer: {
    backgroundColor: "#031f47",
    width: "110%",
    height: 40,
    justifyContent: "center",
    alignContent: "center",
  },
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    marginTop: Constants.statusBarHeight,
  },
  flatList: {
    width: "90%",
  },
  textInput: {
    width: "80%",
    height: 50,
    backgroundColor: "white",
    marginRight: 8,
    borderRadius: 10,
    paddingLeft: 20,
    fontSize: 20,
  },
  textInputContainer: {
    width: "100%",
    justifyContent: "center",
    alignItems: "center",
    flexDirection: "row",
    marginLeft: 10,
  },
  roundButton: {
    height: 60,
    width: 60,
    alignContent: "center",
    justifyContent: "center",
    backgroundColor: "#042048",
    borderRadius: 90,
    marginRight: 10,
  },
  roundButtonIcon: {
    textAlign: "center",
  },
  fromMe: {
    alignSelf: "flex-end",
  },
  fromYou: {
    alignSelf: "flex-start",
  },
  myChat: {
    textAlign: "left",
    fontSize: 18,
    color: "white",
  },
  yourChat: {
    textAlign: "right",
    fontSize: 18,
    color: "white",
  },
  myChatContainer: {
    backgroundColor: colors.MYCHATCOLOR,
    paddingRight: 5,
    paddingLeft: 15,
    paddingTop: 10,
    paddingBottom: 10,
    borderColor: "white",
    borderWidth: 1.5,
    borderTopLeftRadius: 15,
    borderBottomRightRadius: 15,
    borderBottomLeftRadius: 15,
    marginTop: 20,
  },
  yourChatContainer: {
    backgroundColor: colors.YOURCHATCOLOR,
    paddingRight: 15,
    paddingLeft: 9,
    paddingTop: 10,
    paddingBottom: 10,
    borderColor: "white",
    borderWidth: 1.5,
    borderTopRightRadius: 15,
    borderBottomRightRadius: 15,
    borderBottomLeftRadius: 15,
  },
  yourUsername: {
    color: "white",
    fontSize: 20,
    marginBottom: 10,
    marginTop: 10,
  },
});
when the chatscreen loaded all the messages from backend loaded just fine

when i send a new chat message all the array was replaced with just one message

来源:https://stackoverflow.com/questions/64087248/strange-react-native-state-behaviour-while-using-socket-io

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!