DEV Community

Cover image for React Architectures: FLUX vs REDUX
Lovepreet Singh
Lovepreet Singh

Posted on

 

React Architectures: FLUX vs REDUX

๐Ÿ”ฅ Most of us Start our project without thinking about its structure and design. Later on we find difficulties as code gets longer.

๐Ÿš€ In our recent blogs we went through the Basics of Scalability, Deployment and Cloud. Don't worry we'll go in depth with ๐Ÿ˜Ž Youtube tutorials too in future, after covering the basics.

We talked about Clean coding practices, architectures etc. Today we'll talk about most wanted topic:-

๐Ÿคฉ How to Architect our Frontend Project before even starting

๐Ÿ‘‰ Architect/Design the Project well to avoid cluttering afterwards.

Code Cluttering

๐Ÿ“ Note:- Follow on Twitter to get daily value on Open Source, #100daysofCode for building a product end to end and much more...

๐Ÿ“ Define a Good Project directory structure

๐Ÿง‘โ€๐Ÿ’ป Let's see a good practice to define a Project directory:-

Good Project Structure

  • features dir

This is similar to the pages dir but it is different in a way that pages includes different pages like HomePage etc but feature dir contains the specific feature with its components, custom hooks, services and index.js file.

index.js file is used as an API to expose limited functionality(simple export of JS exposes all the code) to the outer code of features.

  • pages dir

It contains only the .js or .tsx files(single files) because logic for a page will go to the features dir and files in pages dir will just glue the different features and some general purpose components(Buttons etc)

  • layouts dir

It is a dir having the layout components like navbar, sidebar etc.

  • lib dir

This dir(as the name states) contains all the wrappers(our code on top of library) inside. For ex: To use Axios you can define axios.js and from there we can use axios library.

  • services dir

This folder contains the code that interacts with other APIs. Having multiple API calls for a feature can be integrated inside the service dir


๐Ÿฅณ Now, we know how our Project Directory should look like. Let's switch over to the Low level design or Laying out our Application workflow.

๐Ÿš€ React FLUX

As a beginner most of us don't follow a preferred flow of data or actions in the app. Means if someone click the button we directly call a function(Buy Smartphone, for say) instead of publishing an action "PRODUCT_BOUGHT". This action could be picked by some service to perform an action, Right?

๐Ÿ˜Ž Exactly, this will make our code very fluent and clean.

THIS IS WHERE FLUX COMES INTO THE PICTURE

React Meme

๐Ÿคฉ FLUX, FLUX, FLUX. In frontend most people do not use recommended design patterns or flows and end up in a code mess.

Let's see how to design a great code flow.

๐Ÿ™‚ What is FLUX design and How is its flow work

React says it is just a view layer not a framework. To make it behave like a framework we use a specific kind of patterns like FLUX and REDUX. Facebook laid out this architecture.

๐Ÿš€ It looks like this:-

Redux Flux architecture

๐Ÿง‘โ€๐Ÿ’ป Let suppose someone clicks on the button Add Post to add his/her post in the social media. So, what can happen is we can design an action and dispatcher like:-

import dispatcher from "../appDispatcher";
import actionTypes from "./actionTypes";
import data from "../db.json";

var posts_list = [
        {
            "id": 1,
            "title": "Hello World",
            "author": "Lovepreet",
            "body": "Example of blog application"
        },
        {
            "id": 2,
            "title": "Hello Again",
            "author": "Singh",
            "body": "Testing another component"
        }
    ]

export function getPosts() {
    dispatcher.dispatch({
        actionTypes: actionTypes.GET_POSTS,
        posts: posts_list,
    });
}
Enter fullscreen mode Exit fullscreen mode
  • Now, Let's say our basic Store is:-
dispatcher.register((action) => {
    switch (action.actionTypes) {
        case actionTypes.GET_POSTS:
            _posts = action.posts;
            store.emitChange();
            break;
        default:
    }
});
Enter fullscreen mode Exit fullscreen mode

We'll register to the dispatcher and will emit/broadcast the event which someone can listen to. Here store.emitChange() is:-

class PostStore extends EventEmitter {
    addChangeListener(callback) {
        this.on(CHANGE_EVENT, callback);
    }

    removeChangeListener(callback) {
        this.removeListener(CHANGE_EVENT, callback);
    }

    emitChange() {
        this.emit(CHANGE_EVENT);
    }

    getPosts() {
        return _posts;
    }
}
Enter fullscreen mode Exit fullscreen mode

and store can be defined from this as:-

const store = new PostStore();
Enter fullscreen mode Exit fullscreen mode

๐Ÿ˜‡ Now, we can see that we have store which is listening to the events/actions and getting some data/payload. It is then changing or not changing the values/state of some things and then emitting an event through Emitters.

And Now in view we can listen for the changes and can change accordingly:-

useEffect(() => {
    setposts(data["posts"]);
}, []);
Enter fullscreen mode Exit fullscreen mode

๐Ÿ˜Ž To sum it up:-

React Flux Flow

[Credits:- freecodecamp]

๐Ÿ˜Ž Now, React REDUX ๐Ÿคฉ

As, we saw React is only capable of showing something, monitoring the dom for state changes and passing props. React FLUX makes it a full framework capable of doing more than that.

๐Ÿ”ฅ Now, React REDUX is the implementation on top of FLUX and most widely used. It looks like:-

React Redux architecture

๐Ÿ“ In REDUX, we have Actions, Dispatcher and Reducers inside the store. Reducers are nothing but the functions that can be triggered on arrival of some action through dispatcher and then can change the state of the app.

๐Ÿ‘‰ In Redux only different thing is we have reducers. A reducer can look like:-

function nextTodoId(todos) {
  const maxId = todos.reduce((maxId, todo) => Math.max(todo.id, maxId), -1)
  return maxId + 1
}

// Use the initialState as a default value
export default function appReducer(state = initialState, action) {
  // The reducer normally looks at the action type field to decide what happens
  switch (action.type) {
    // Do something here based on the different types of actions
    case 'todos/todoAdded': {
      // We need to return a new state object
      return {
        // that has all the existing state data
        ...state,
        // but has a new array for the `todos` field
        todos: [
          // with all of the old todos
          ...state.todos,
          // and the new todo object
          {
            // Use an auto-incrementing numeric ID for this example
            id: nextTodoId(state.todos),
            text: action.payload,
            completed: false
          }
        ]
      }
    }
    default:
      // If this reducer doesn't recognize the action type, or doesn't
      // care about this specific action, return the existing state unchanged
      return state
  }
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ˜Š Depending on the functionality, an app can have multiple reducers like:

header: headerReducer
payment: paymentReducer
home: homeReducer
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”ฅ Our app at the end can have one root reducer, so we have to combine the different reducers:-

import { combineReducers } from 'redux'

import todosReducer from './features/todos/todosSlice'
import filtersReducer from './features/filters/filtersSlice'

const rootReducer = combineReducers({
  // Define a top-level state field named `todos`, handled by `todosReducer`
  todos: todosReducer,
  filters: filtersReducer
})

export default rootReducer
Enter fullscreen mode Exit fullscreen mode

Now, to create Store we have a basic function from redux

import { createStore } from "redux";
import { currencyReducer } from "./reducers/rootReducer";

const appStore = createStore(rootReducer);

export default appStore;
Enter fullscreen mode Exit fullscreen mode

๐Ÿ‘€ Now, Suggest me the choice on our next Blog on:-

React project using

  1. FLUX
  2. REDUX

Choose and Comment.....

๐Ÿ˜Š That was it for today. Kindly Share with your friends and on your social media ๐Ÿฅ

Top comments (5)

Collapse
 
bigfree profile image
Adam Mikรณ

aaaand winner is zustand! โค๐Ÿ˜‚

Collapse
 
anupam_kumar_faf1abd75050 profile image
anupam kumar

Yeah. Best way to avoid boilerplate.

Collapse
 
lovepreetsingh profile image
Lovepreet Singh

Thanks brother ๐Ÿš€

Collapse
 
mohmmadaslam profile image
Mohmmad Aslam

Nice

Collapse
 
lovepreetsingh profile image
Lovepreet Singh

๐Ÿ˜‡