Search code examples
node.jsreactjsreduxreact-reduxreact-fullstack

React fullstack architecture: When adding a react front-end to a node/express application, what aspects does react's state generally handle?


I have a fully built node/express application that I want to add react to in order to practice that relationship in full stack applications. I've built apps in react before, and in node, but never together and I am confused about how react fits into the MVC architecture.

In a react-node full stack application does react state then handle all of the data I was previously passing into my ejs views?

I have been looking through tutorials on full stack applications with node and react, but they only seem to go into issues like how does react fetch data from the back end, or how to set up the configuration, but I get that part, I just don't understand what react does in a full stack application, what part of the model-controller-view architecture of a node/express backend app does react take over? How are the responsibilities split between the backend and front end?

So for example, I'm working with a reddit-clone type app so when you click on a post title to see the post my controller queries the database for that post and then passes it to the view as {post}:

show(req, res, next){
        postQueries.getPost(req.params.id, (error, post) => {
            if(error || post == null){
                res.redirect(404, "/");
            } else {
                res.render("posts/show", {post});
            }
        });
    },

So when I add a front-end with react, would that {post} object then be something handled by react? So react would fetch that data and use it in a post component to create what is currently my view show.ejs file?


Solution

  • So when I add a front-end with react, would that {post} object then be something handled by react? So react would fetch that data and use it in a post component to create what is currently my view show.ejs file?

    Yes. The show.ejs would be a React view or a page that contains a component to handle how to show it.

    To simplify:

    React -- is a virtual DOM, so it'll swap views/containers/components in and out based upon events (like clicking a button), which in turn, will: retrieve, display, manipulate and/or send data to the API. In development, it is completely separate from your back-end. All the routing will be handled by a front-end router package. In production, all of the front-end src code is compiled into a dist or build folder that contains your assets (images, fonts, css) and most importantly bundle.js file(s) that are then served by express.

    Express + some database -- will act as your API where it'll CRUD data based upon the front-end request(s). If your app is a MPA (multiple page application), then a common practice is to delineate your back-end routes from your front-end routes with a /api/ prefix. In production, if express doesn't recognize the route (it's not a /api/ request), then it'll fall back into the front-end bundle.js file where it'll be handled by the front-end router.

    See a working example here: https://github.com/mattcarlotta/fullstack-mern-kit (client is the frontend, everything else is the backend)

    Or

    See a working codesandbox (where I'm making a GET request to an API that returns json):

    Edit Restructured App


    For your example above, your show controller will just be sending JSON (or a string message) back to the frontend (redirects will happen on the frontend via a router -- like react-router-dom):

    show(req, res, next){
            postQueries.getPost(req.params.id, (error, post) => {
                if(error || post == null){
                    // res.status(404).send("Unable to locate posts.");
                    res.status(404).json({ err: Unable to locate posts });
                } else {
                    res.status(200).json({ post });
                }
            });
        },
    

    You can even simplify the above using async/await:

    const show = async (req, res, done) => {
            try {
               const post = await postQueries.getPost(req.params.id);
               res.status(200).json({ post });
            } catch(err) {
               // res.status(404).send("Unable to locate posts.");
               res.status(404).json({ err: Unable to locate posts });
            }
        };
    

    And then the React front-end handles the response.