skip to Main Content

I have a mern social media app where user can log in and then are taking to their feed where they can create posts and they are displayed on the feed. Everything works on the localhost but on the server I can log in and see the feed and can even create posts that are being saved to the database but they are not being shown on the feed on there server.

This is the server.js:

const path = require('path');
const express = require('express');
const cors = require('cors');
const fileUpload = require('express-fileupload');
const AuthRoute = require('./routes/AuthRoute.js');
const connectDB = require('./config/db.js');
const colors = require('colors');
const dotenv = require('dotenv');
dotenv.config();

const PostRoute = require('./routes/PostRoute.js');
const UploadRoute = require('./routes/UploadRoute.js');

const PORT = process.env.PORT || 8000;

connectDB();

const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cors());

// Serve frontend
if (process.env.NODE_ENV === 'production') {
  app.use(express.static(path.join(__dirname, '../frontend/build')));

  app.get('*', (req, res) =>
    res.sendFile(
      path.resolve(__dirname, '../', 'frontend', 'build', 'index.html')
    )
  );
} else {
  app.get('/', (req, res) => res.send('Please set to production'));
}

app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}.`.yellow.bold);
});

app.use('/api/auth', AuthRoute);
app.use('/api/posts', PostRoute);
app.use('/api/uploadImages', UploadRoute);

I’ve tried moving things around but it hasn’t changed anything.
This is my PostRoutes:

const express = require('express');
const {
  createPost,
  getTimelinePosts,
  getAllPosts,
} = require('../controllers/PostController.js');
const { authUser } = require('../middleware/auth');

const router = express.Router();
console.log('inside am in the routes');
router.post('/createPost', createPost);
router.get('/:id/timeline', getTimelinePosts);
router.get('/getAllPosts', authUser, getAllPosts);
module.exports = router;

Below is where the are initially being called and on the localhost and if I comment out all the code except the useEffect it shows the array of posts in the console but in the server console it shows the html doc.

Here is the file:

import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getTimeLinePosts } from '../../../actions/postAction';
import Post from '../Post/Post.js';
import PulseLoader from 'react-spinners/FadeLoader';

const Posts = () => {
  const dispatch = useDispatch();
  const { user } = useSelector((state) => state.authReducer.authData);
  const { posts, loading, error } = useSelector((state) => state.postReducer);

  useEffect(() => {
    if (error) {
      console.log(error);
    }
    dispatch(getTimeLinePosts(user._id));
  }, [dispatch, user._id]);

  return (
    <div className="Posts">
      {loading ? (
        <div style={{ display: 'flex', justifyContent: 'center' }}>
          <PulseLoader
            color="#485639"
            height={15}
            width={5}
            loading={loading}
          />
        </div>
      ) : posts ? (
        posts.map((post, i) => (
          <Post key={i} post={post} index={i} user={user} />
        ))
      ) : (
        "You haven't shared anything yet."
      )}
    </div>
  );
};

export default Posts;

Here is the postRequest

import axios from 'axios';
//import * as PostsApi from '../api/PostsRequests';

export const getTimeLinePosts = (id) => async (dispatch) => {
  console.log(id);
  const API_URL = '/api/posts/';
  dispatch({ type: 'RETREIVING_START' });
  try {
    //const { data } = await PostsApi.getTimelinePosts(id);
    const { data } = await axios.get(`/api/posts/${id}/timeline`);
    console.log(data);
    dispatch({ type: 'RETREIVING_SUCCESS', data: data });
  } catch (error) {
    dispatch({ type: 'RETREIVING_FAIL' });
    console.log(error);
  }
};

And here is the postReducer

const postReducer = (
  state = { posts: null, loading: false, error: false, uploading: false },
  action
) => {
  switch (action.type) {
    // belongs to PostShare.jsx
    case 'ADDPOST_START':
      return { ...state, error: false, uploading: true };
    case 'ADDPOST_SUCCESS':
      return {
        ...state,
        posts: [action.data, ...state.posts],
        uploading: false,
        error: false,
      };
    case 'ADDPOST_FAIL':
      return { ...state, uploading: false, error: true };
    // belongs to Posts.jsx
    case 'RETREIVING_START':
      return { ...state, loading: true, error: false };
    case 'RETREIVING_SUCCESS':
      return {
        ...state,
        posts: action.data,
        loading: false,
        error: false,
      };
    case 'RETREIVING_FAIL':
      return { ...state, loading: false, error: true };
    default:
      return state;
  }
};

export default postReducer;

2

Answers


  1. Short answer: The lines serving static assets should be placed after all the other routes in the server file.

    Long answer: Please put the following lines

    // Serve frontend
    if (process.env.NODE_ENV === 'production') {
      app.use(express.static(path.join(__dirname, '../frontend/build')));
    
      app.get('*', (req, res) =>
        res.sendFile(
          path.resolve(__dirname, '../', 'frontend', 'build', 'index.html')
        )
      );
    

    after the following lines:

    app.use('/api/auth', AuthRoute);
    app.use('/api/posts', PostRoute);
    app.use('/api/uploadImages', UploadRoute);
    

    Express JS interprets routes based on the order they are written in the server file, therefore the static assets should be served after all the other routes. This should solve the problem you are having.

    Login or Signup to reply.
  2. The problem is you’re conditionally adding a catch all handler app.get("*") to the express pipeline, which will make your api routes unreachable. The express.static middleware is already handling paths that are mapped to physical files, in case no file found, it just passes the request to the next middleware.

    A possible fix could be a refactor in code, maybe just remove the check for production and the catch all handler.

    Notice that the api routes should be set before calling app.listen().

    
    const app = express();
    app.use(express.json());
    app.use(express.urlencoded({ extended: false }));
    app.use(cors());
    
    // Serve frontend
    
    app.use(express.static(path.join(__dirname, '../frontend/build')));
    
    app.use('/api/auth', AuthRoute);
    app.use('/api/posts', PostRoute);
    app.use('/api/uploadImages', UploadRoute);
    
    app.listen(PORT, () => {
      console.log(`Server is running on port ${PORT}.`.yellow.bold);
    });
    
    
    

    I don’t know why you’re enforcing for production mode in NODE_ENV, the app should work in either environments.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search