Socket.io not populating appropriate changes


I’m currently in the process of learning, by building out a social platform; I’m making use of MongoDB, Express, React as the structure, for updating the state real-time, I’m making use of Mongo Change Streams where it’s implied with socket.io for applying the changes. Previously I’ve had everything working, but I’ve come across a limitation to my comment and reply section, due to me wanting to apply nested replies on comments. This forced me to change my document structures, where I’ve previously made use of nested array’s containing comments and likes in the post document, there by me changing post, comments and likes to separate documents, by making use of .populate() to share data between documents. With the Nested array schema changes were a lot easier to detect with socket.io, but now that everything has changed, my issue is that when I apply comments or any replies it seems that my changes being set through socket.io isn’t including the populated data, thus not applying the real-time effect to newly created replies or comments.

Change Stream (Server.js)

const db = mongoose.connection;
db.once('open', () => {
    console.log(chalk.blueBright("Setting change streams"));
    db.collection('posts').watch()
    .on('change', change => {
        if(change.operationType === 'insert'){
            console.log(chalk.yellowBright('INSERTED LIKE'))
            io.emit('posts', change.fullDocument);
            console.log(change.fullDocument)
        }
    });
    db.collection('posts').watch({ fullDocument: 'updateLookup' })
    .on('change', change => {
        if(change.operationType === 'update'){
            console.log(chalk.yellowBright('UPDATED LIKE'));
            io.emit('posts', change.fullDocument);
            console.log(change.fullDocument)
        }
    })

}); 

Post Model

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Populate = require('../utils/autopopulate');

const postSchema = new Schema({
    uid: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
    uname: {type: String, required: true},
    upic: {type: String, required: true},
    message: { type: String,},
    media: {type: String,},
    comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'comments' }],
    commentCount: {type: Number, default: 0},
    likeCount: {type: Number, default: 0},
    repostCount: {type: Number, default: 0},
    postedOn: { type: Date},
});

postSchema.pre('save', function(next){
    this.postedOn = Date.now();
    next();
})


var PostModel = mongoose.model('posts', postSchema);

module.exports = PostModel;

Post Controller

exports.getPosts = (req, res) => {
    try {
        PostModel.find({}).lean().populate('comments')
        .then((posts) => res.status(200).json(posts))
        .catch((err) => {
          console.log(err.message);
        });
    } catch(error) {
        throw new ErrorResponse('Posts could not be found', 404);
    }
}

Front-End (socket.io)

//Post section
const [posts, setPosts] = useState([]);

//Get posts
    useEffect(() => {
       axios.get("/api/post/posts", config).then((response) => {
           setPosts(response.data);
       });
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    //Check socket changes
    useEffect(() => {
      const handler = (item) => {
        setPosts((oldPosts) => {
          const findItem = oldPosts.find((post) => post._id === item._id);
          if (findItem) {
            return oldPosts.map((post) => (post._id === item._id ? item : post));
          } else {
            return [item, ...oldPosts];
          }
        });

        
      };
      socket.on("posts", handler);
      return () => socket.off("posts", handler);
       //eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

On the getPost() controller, the data is being perfectly populated, but only when the second useEffect is occurring to check changes, it seems not be applying those populated data of comments, now I have had previous help with this useEffect when I was working with the nested array Post schema, but how would I apply this now after the changes I have done, which has been mentioned above.

Source: React – Stack Overflow

November 4, 2021
Category : News
Tags: mongodb | mongoose | reactjs | sockets | use-effect

Leave a Reply

Your email address will not be published. Required fields are marked *

Sitemap | Terms | Privacy | Cookies | Advertising

Senior Software Developer

Creator of @LzoMedia I am a backend software developer based in London who likes beautiful code and has an adherence to standards & love's open-source.