question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Low performance in React Native with Redux

See original GitHub issue

I have discovered some issues with performance in my react native app. It seems to be caused by react-redux bundle.

As you can see in the video

https://youtu.be/D5L-RM5EY5E

there is a significant delay between action dispatching and view rendering. On real devices it looks even worse. There are no API calls in this example. Only simple actions dispatching and state changes. On other hand Facebook Flux implementation and simple call of setState work much more faster.

Any ideas how to improve the app performance?

I am using react: v15.2.1, react-native: v0.29.2, react-redux: v4.4.5, View

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

import {Map} from 'immutable';

import * as testActions from '../reducers/test/testActions';
import {Actions} from 'react-native-router-flux';

const actions = [
  testActions
];

function mapStateToProps(state) {
  return {
      ...state
  };
}

function mapDispatchToProps(dispatch) {
  const creators = Map()
          .merge(...actions)
          .filter(value => typeof value === 'function')
          .toObject();

  return {
    actions: bindActionCreators(creators, dispatch),
    dispatch
  };
}

........

<View style={styles.box}>
    {PRICE_FILTERS.map(filter =>{
        let price_cont_style = {};
        let price_text_style = {};
        if (filter.id == PRICE_FILTERS[3].id){
            price_cont_style.marginRight = 0;
        }
        if (filter.id == this.props.test.price){
            price_cont_style.backgroundColor = 'black';
            price_text_style.color = 'white';
        }
        return(
        <TouchableOpacity 
            key={filter.id} 
            style={[styles.price_cont, price_cont_style]} 
            onPress={()=>this.props.actions.setPrice(filter.id)}>
        <Text 
            style={[styles.price_text, price_text_style]}>
            {filter.label}
        </Text>
        </TouchableOpacity>
        );
    })}
</View>

......

export default connect(mapStateToProps, mapDispatchToProps)(PerformanceTest);

Actions

const {
    TEST_SET_PRICE,
} = require('../../lib/constants').default;

export function setPrice(filter) {
  return {
    type: TEST_SET_PRICE,
    payload: filter
  };
}

Reducer

const {
    TEST_SET_PRICE,
} = require('../../lib/constants').default;
const InitialState = require('./testInitialState').default;
export default function authReducer(state = InitialState, action) {
  switch (action.type) {

  case TEST_SET_PRICE:
        if (state.price!=action.payload){
            return {price:action.payload}
        } else{
            return state;
        }

    }
    return state;
}

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:3
  • Comments:35 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
alsh76commented, Jul 13, 2017

@davidsamacoits If you are using v4 hopefully you can omit first step https://github.com/aksonov/react-native-router-flux#v4-features each ‘scene’ could have onEnter/onExit handlers. Access to your app navigations state as simple as Actions.state, use Actions.currentScene to get name of current scene. I hope that helps

2reactions
alsh76commented, Jul 13, 2017

oh that was a bit tricky. I used old v3 First step was creating a custom reducer. It tracked navigation events and saved it in special redux store

   reducerCreate(params){
        const defaultReducer = Reducer(params);
        return (state, action)=>{
            switch (action.type) {
                case ActionConst.PUSH:
                    //fired on regular scene-to-scene transition
                    //you can detect active scene key by action.key
                    store.dispatch(navigationPush(action.key));
                    break;
                case ActionConst.BACK_ACTION:
                    //fired on android back action
                    store.dispatch(navigationBack());
                    break;
                case ActionConst.JUMP:
                case ActionConst.REFRESH:
                    //fired on tab switching
                    //action.key points on active tab
                    store.dispatch(changeTab(action.key));
                    break;
                case ActionConst.POP:
                case ActionConst.POP_TO: 
                    //fired on Action.pop()
                    store.dispatch(popTo(action.scene));
                    break;
                case ActionConst.FOCUS:
                    //immediately fired on any new scene opening
                    //it does not wait end of transition 
                    //....
                    break;
            }
            return defaultReducer(state, action);
        }
    }

....

  render() {
    return (
        <Provider store={store}>
        <Router createReducer={this.reducerCreate}>
        <Scene key="root">
        ....
	    </Router>
	    </Provider>

Second step - override shouldComponentUpdate in every your scene component

class SomesSceneComponent extends Component{

    shouldComponentUpdate(nextProps, nextState){
        //check navigation redux store for active tab and scene
        if (this_scene_is_not_active){
            return false;
        }
        return true;
    }
.....
Read more comments on GitHub >

github_iconTop Results From Across the Web

3 small tips for better Redux performance in a React app
3 small tips for better Redux performance in a React app · 1. Make use of memoization in your selectors · 2. Use...
Read more >
Redux in React Native app is very slow with lots of data
My best attempt to profile this issue is via slowlog , which is where I came up with the 500ms figure for the...
Read more >
Redux FAQ: Performance
If you actually are concerned about reducer performance, you can use a utility such as redux-ignore or reduxr-scoped-reducer to ensure that only ...
Read more >
Dealing with performance issues in React Native - Medium
The issue with Native apps is that even though users have higher expectations for their apps than the Web, they have weak CPUs,...
Read more >
Redux isn't slow, you're just doing it wrong - An optimization ...
When optimizing applications that use Redux with react, I often hear people saying that Redux is slow. In 99% of cases, the cause...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found