cavaleria
cavaleria

Reputation: 1475

When to use Redux?

I am currently writing a MERN stack application and I seem to be handling state well as I appreciate using the modular concepts behind React.

I have seen Redux get very popular, but from my basic understanding, it seems to take all states and store them in a single store.

Currently I am storing a prop called isMobile simply declaring whether I am in a mobile state or not. I am currently passing that down to every component as needed to adjust accordingly. Does Redux help with a situation like this? If not, what are the real benefits while using React.

Upvotes: 2

Views: 1756

Answers (3)

Gunnar Siréus
Gunnar Siréus

Reputation: 192

When using Redux in React you’ll notice that there are two types of states: global, which are immutable and changed via actions and local states which are handled the usual way.
A good way to learn Redux in React is to go through Dan Abramow’s Getting Started with Redux:

https://egghead.io/courses/getting-started-with-redux

You will notice that the React code in the tutorial has no life cycle hooks, each component only renders html. All states are global and changed via actions.

However, in a bigger application using Redux there will usually be both local and global states and they will have to interact with each other. This adds extra complexity to your application.

Please see https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367

Upvotes: 0

markerikson
markerikson

Reputation: 67577

The Redux FAQ answers this specific question at http://redux.js.org/docs/faq/General.html#general-when-to-use :

In general, use Redux when you have reasonable amounts of data changing over time, you need a single source of truth, and you find that approaches like keeping everything in a top-level React component's state are no longer sufficient.

I also recently co-authored an article that discusses the benefits of using Redux in a React application. The summary is that keeping your application's state outside the component tree can make data flow simpler, especially in cases like the one you described.

Upvotes: 3

Yo Wakita
Yo Wakita

Reputation: 5460

I do sometimes find it useful to have a window reducer that keeps track of things like screen size, scroll height, and other attributes that some of my components would rely on. I would create an action creator that I set at the top level component so that any resize or scroll action may update the redux store, and that way, I wouldn't need to attach those handlers on each component that is dependent on window properties.

Note that this could get heavy performance-wise, so using a debounce and/or throttling function to reduce the amount of times the action is fired off is essential.

So in either a wrapper component for your app or in your top-most component, you could do something like this:

import { throttle, debounce } from 'lodash';

...
...

constructor(props){
    super(props);
    this.scrollHandler = this.scrollHandler.bind(this);
    this.resizeHandler = this.resizeHandler.bind(this);
    this.update = this.update.bind(this);
}

scrollHandler() {
    throttle(this.update, 250)();
}

resizeHandler() {
    debounce(this.update, 500)();
}

update() {
    const { updateWindow } = this.props;
    const {
        innerHeight,
        innerWidth,
        outerHeight,
        outerWidth,
        pageYOffset,
        scrollY
    } = window;

    updateWindow({
        innerHeight,
        innerWidth,
        outerHeight,
        outerWidth,
        pageYOffset,
        scrollY
    });
}

componentDidMount() {
    this.update();
    window.addEventListener('scroll', this.scrollHandler, false);
    window.addEventListener('resize', this.resizeHandler, false);
}

componentWillUnmount() {
    window.removeEventListener('scroll', this.scrollHandler, false);
    window.removeEventListener('resize', this.resizeHandler, false);
} 

And the reducer might look something like this:

const DEFAULT_WINDOW = {
    innerWidth: 0,
    innerHeight: 0,
    outerWidth: 0,
    outerHeight: 0,
    pageYOffset: 0,
    scrollY: 0,
    scrollingUp: false,
    scrollingDown: false
};

const window = (
    state = DEFAULT_WINDOW,
    action
) => {
    const { data } = action;
    switch (action.type) {
        case types.UPDATE_WINDOW:
            return assign({}, state, data, {
                scrollingUp: data.pageYOffset < state.pageYOffset,
                scrollingDown: data.pageYOffset > state.pageYOffset
            });
        default: return state;
    }
};

Upvotes: 1

Related Questions