Home > Mobile >  Functional style React Native component successfully calls Redux Action but Class style component do
Functional style React Native component successfully calls Redux Action but Class style component do

Time:07-21

I have a Functional style React Native component where I can happily call my Redux Action:

import * as React from 'react';
import {Text, View, StyleSheet, Dimensions} from 'react-native';
import MultiSlider from '@ptomasroos/react-native-multi-slider';
import {useSelector, useDispatch} from 'react-redux';
import {updateNumPosInCode} from './redux/actions/gameplayAction';

const width = Dimensions.get('window').width;

export default function Settings() {
  const dispatch = useDispatch();

  const numPosInCode = useSelector(store => store.gameplay.numPosInCode);

  const handleNumPosInCodeUpdate = num => {
    console.log(`handleNumPosInCodeUpdate: ${num}`);
    dispatch(updateNumPosInCode(num));
  };

  return (
    <View style={[styles.container]}>
      <View>
        <Text style={styles.text}>Number of Positions in the Code</Text>
        <MultiSlider
          sliderLength={width - 40}
          values={[6]}
          optionsArray={[4, 5, 6]}
          snapped={true}
          onValuesChangeFinish={handleNumPosInCodeUpdate.bind(this)}
        />
        <Text style={styles.text}>{numPosInCode}</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flexDirection: 'column',
    flex: 1,
    padding: 20,
    justifyContent: 'space-evenly',
  },
  text: {
    textAlignVertical: 'center',
    textAlign: 'center',
  },
});

However when I try to call the same action from this Class style React Native component, nothing happens. Can you spot my mistakes?

import * as React from 'react';
import {View, StyleSheet, Button} from 'react-native';
import {connect} from 'react-redux';
import {updateNumPosInCode} from './redux/actions/gameplayAction';

class ColourBoard extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      numPosInCode: 5,
    };
  }

  render() {
    return (
      <View
        style={[
          styles.MainContainer,
          {
            top: this.state.top,
          },
        ]}>
        <Button
          onClick={this.props.updateNumPosInCode(4)}
          title="Test"
          color="#841584"
        />
      </View>
    );
  }
}

const mapStateToProps = state => ({
  numPosInCode: state.numPosInCode,
});

// Actions:
const mapDispatchToProps = () => ({
  updateNumPosInCode,
});

const styles = StyleSheet.create({
  MainContainer: {
    left: 1,
    justifyContent: 'center',
    alignItems: 'center',
    height: '100%',
    width: '100%',
    position: 'absolute',
    zIndex: 1,
  },
});

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

CodePudding user response:

Yes. Your mapDispatchToProps usage is wrong.

With connect, there's two ways to use mapDispatch:

  • passing in an object full of action creators, in which case you get all the same functions as props but already wrapped up to dispatch actions when called
  • passing in a function that gets dispatch as an argument, in which case it's up to you to do the wrapping

In this case, you're passing in the function form of mapDispatch... **but you are only returning the plain action creators as the props, and not wrapping them to make use of dispatch!

The simplest answer here is to change it to const mapDispatch = {updateNumPosInCode} and pass that instead.

The better answer is to switch this to be a function component and make use of the useDispatch hook instead.

  • Related