0

In my app, I have a function which calls every 2s a bluetooth command to ask the current temperature of a device with a setInterval function.

The bluetooth response is given by monitored function. I use react native-ble-plx library for that. I have no problem with this process.

The temperature is returned via a property which is dispatched via redux in an action file. But when I "dispatch" (via redux) the function to my screen, I have a short interrupt which causes a laggy/jerky behavior. In my case, I have a slide to unlock button, and on my device when the dispatch is call, the touch operation is interrupted, and become not intuitive and annoying. It's difficult to explain the problem, but my question is simple, how I have to set react-redux not to be laggy, or not interrupt current user interaction on redux dispatch ?

My app, is based on this project structure (for react-redux with Ble) : https://github.com/momolarson/BLEServiceDiscovery

Environement: react-native: 0.63.3

react-native-ble-plx: 2.0.2

react-redux: 7.2.1

This is pseudo code of my app (the code is more longer, but I have excluded all other by remove them) :

HomeScreen.js

import stuff[...]

class HomeScreen extends Component {

    componentDidMount() {
        this.timer = setInterval(() => {
            this.props.readTemp();
        }, 2000);
    }

    render() {
        const { value } = this.state
        
        return (
            <>
            <ScrollView>
                <Text>{this.props.temperatture}"></Text>
                <Slide2Unlock/>
            </ScrollView>
            </>
        );
    }
}

function mapStateToProps(state) {
    return {
        temperature: state.temperature,
    };
}


const mapDispatchToProps = dispatch => ({
    readTemp: () => bluetooth.readTemp(),
})


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

redux's action file : actionBt.js (my file is based on this https://github.com/momolarson/BLEServiceDiscovery/blob/master/actions/index.js)

[...]
device.monitorCharacteristicForService(
    characteristicData.serviceUUID,
    characteristicData.uuid,
    (error, characteristic) => {
        if (characteristic != null && characteristic.value != null) {
            dispatch(formatTemperature(characteristic.value));
        }
    },
);

thanks for your help

Update 1

I make a specific version of my app, without bluetooth, just the slide to unlock module and a watcher with setInterval, and still have a laggy behavior, when the state is dispatched. I have done tests with button only, when I tap then show the value via dispatch, it's still the same trouble.

this my test code, index.js (redux action file)

export const readTemp = () => {
    return (dispatch, getState, DeviceManager) => {
        const state = getState();
        console.log("READ TEMP");
        dispatch(temperatureSensor( Math.random(0,9) ))
    }
}
function BLEservices(BLEServices) {

    setInterval(() => {
        BLEServices.readTemp();
    }, 2500);

    return (
        <SafeAreaView style={styles.container}>
            <Slider
                childrenContainer={{  }}
                onEndReached={() => {
                    console.log('REACHED')
                }}
                containerStyle={{
                    height:40,
                    margin: 8,
                    backgroundColor: "#EEEEEE",
                    overflow: 'hidden',
                    alignItems: 'center',
                    justifyContent: 'center',
                    width: '50%',
                }}
                sliderElement={
                    <Text style={{color:"#FFF"}}>TEST</Text>
                }
            >
                <Text style={{color: "#D5BD9E"}}>unlock</Text>
            </Slider>

            <Text>Temperature: {BLEServices.temperatureSensor}</Text>

        </SafeAreaView>
    );
}

thanks for your advice, and your help

Update 2

Solution found, see my answer below. The problem was type of var user in dispatch and some side effect due to previous test I have done on app and not clean them.

Gusse
  • 1
  • 4
  • When you dispatch readTemp, it calls something from the device? If you comment out the function of the device is it still laggy? From my years of working with react-native and redux, I don't think it's the cause of the behavior you are experiencing. – Someone Special Nov 27 '20 at 21:27
  • I don't see where you are clearing your interval, i don't think redux is the issue, i believe is your interval, there must be a lot of intervals being created on every render and saturating the js thread. – Charlie Nov 27 '20 at 22:26
  • thanks for your advice. I have done some tests by replacing `dispatch(formatTemperature(characteristic.value));` with a simple console.log, I get value in my console correctly and the laggy behavior has disapeared, but I have to use `dispatch()` function to get value in my interface. If you have an another idea to avoid to use that and re-render I'm open to suggestions. I have a clear interval when I quit the current page, but I need to have the temperature in "real time" – Gusse Nov 28 '20 at 17:19
  • Is the state change in your reducer immutable? Sometimes if you don't have this, it makes it slow as well. – Kielstra Nov 30 '20 at 08:45
  • sorry I'm beginner with redux, what did you mean concretly by reducer immutable ? I have this code in my reducer : ```react case 'TEMPERATURE_SENSOR': return update(state,{temperatureSensor: {$set: action.temperatureSensor} }); ``` Is what you mean ? – Gusse Nov 30 '20 at 09:36
  • I adjust my code to this: ```case 'TEMPERATURE_SENSOR': return { ...state, temperatureSensor: action.temperatureSensor }``` still the same problem – Gusse Nov 30 '20 at 10:25

1 Answers1

0

I solved my problem, by finding multiple var who are contains objects. I have a var which contain four attributes, I update and use one of them. And this object was update by my watcher. When I dispatch object to get a part of this object, I have to read the whole object, and this one is fully updated by my watchern which cause laggy render. So i have splitted that, to update only per var. Another thing I've done, I split my interface elements in multi component, before, I has a lot of code in one screen, because I didn't need to reuse them elsewhere.

Gusse
  • 1
  • 4