0

This is my first attempt at creating something with react and redux. So my goal is to build a data table. (I probably could have used some existing ones, but I wanted to challange myself with this).

The table renders rows only visible on the screen, you can show/hide/swap/pin/resize columns, and every action like this also save profile in localstorage. Rows can be filtered, edited and "checked" to do some other actions with them. So the component is pretty comprehensive, with lots of features. I have basically done it, and it works.

But I used redux, and, by following any example online - they say "make one connected component per 'logical' component".

So I did it - I have 1 reducer for whole table. But only now, I noticed a serious lag.

When I try to type in "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" in 1 filter input, it hangs up pretty severely.

The input cell is rather simple -

<input ref={el => this.input = el} className="form-control" type="text" value={this.props.value} onChange={this.handleChange} />

And handleChange() dispatches this event to reducer

handleChange(evt) {
    this.props.onFilterInputChange({fieldName: this.props.fieldName, value: this.input.value});
}

And the reducer is a simple one aswell

case types.ON_FILTER_INPUT_CHANGE: {
    const spec = {
        currentFilter: {
            [action.params.fieldName]: { $set: action.params.value }
        }
    };
    return update(state, spec);
}

Chrome performace tool records this awful thing as this: Chrome performace tools while typing "aaaaaaaaaaaaaaaaaaaaaaaaa"

From examples - many said this:

React-redux rerenders only the things that change

But that was not true. It calls render() for all of the things in the component and that is why my table works so slow. I have not added shouldComponentUpdate() to any of my components.

My question is: how do I make it work faster?

Would adding this to all of my components make it better?

shouldComponentUpdate(newProps, newState) {
    let keys = Object.keys(this.props);
    let result = false;
    for (let i = 0; i < keys.length; i++) {
        if (this.props[keys[i]] !== newProps[keys[i]]) {
            result = true;
            break;
        }
    }
    return result;
}

It seems to make it a bit more responsive.

But I had doubts about redux before this - storing all of the state in a single atom..

1 Answer 1

1

Its a bit complicated subject but worth the effort. Some pointers from my earlier answer:

apart from this

1) Use shouldComponentUpdate/React.PureComponent only if react-perf shows less renders, else your application can give hard-to-debug bugs

2) For components getting more renders(V-DOM renders), use componentWillUpdate to check the cause by diffing old and new props and state. Try reducing renders of parent component first and then move toward child, as if parent renders, child will definitely render, no matter whether its props or state changes or not.

3) Use debouncing onchange handler ref

4) Although easiets but very good improvement would be noticed, if you can batch your actions by redux-batched-middleware

Remember react always runs its diffing algorithm and produces a new V-DOM on every render, no matter whether physical dom changes or not. You can help reducing these renders with my pointers.

Sign up to request clarification or add additional context in comments.

6 Comments

Although you say I should avoid using shouldComponentUpdate/ React.PureComponent - that is the only way I can prevent render() calls (your 2nd point), no? Without them, it calls render() for all of the components in all of the DOM tree for the component. So this is The only way to limit render calls(). I think I have no place, where batched action calls would benifit.
There are many ways to prevent render. render happens when either parent renders or a prop/state of this component changes. Whether prop/state changes you can find by putting componentWillUpdate hook and comparing prev and next props/state. If none changes then move to its parent, right uptill the root, to find which parent is the root cause of rendering. After finding use shouldComponentUpdate only there, but many a times prop changes just because of say we send new empty object or new bound function to children, correct that first, if found.
Also every action causes a render of whole tree. When you type, many actions are dispatched in very less time, amounting to many renders and hence lag is noticed. If you batch actions, only 1 render will happen for actions coming together in bulk, as in typing.
Please read my linked answer as I mentioned all this there also.
I was passing whole reducer store object to very top components. I guess that is a big no-no. Since it will change every time anything in it changes.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.