Lukas
Lukas

Reputation: 340

React-Native Redux unable to set state

I use Redux to set three Counters for my navigation bar. I can access the values in initial state. But I am unable to change the values. My Reducer looks like this:

const SET_FREUNDE = 'SET_FREUNDE';
const SET_CHATS = 'SET_CHATS';
const SET_VOTES = 'SET_VOTES';

export function setFreunde(value) {
  return {
    type: SET_FREUNDE,
    value,
  }
}

export function setChats(value) {
  return {
    type: SET_CHATS,
    value,
  }
}

export function setVotes(value) {
  return {
    type: SET_VOTES,
    value,
  }
}

const defaults =
  {
    countervotes: 2,
    counterchats: 1,
    counterfreunde: 1
  };


function counter(state=defaults, action) {
  switch (action.type) {
    case SET_FREUNDE:
      return {...state,counterfreunde: action.value}
      case SET_CHATS:
        return {...state,counterchats: action.value}
        case SET_VOTES:
          return {...state,countervotes: action.value}
    default:{
      return state;
    }
  }
}

export default counter;

Now I want to set the counters on a other screen:

import * as React from "react";
import { Image, StyleSheet,... } from "react-native";
...

import {connect} from 'react-redux';
import { setChats, setFreunde, setVotes } from '../redux/counter';

class ... extends React.Component<{}, State> {

  constructor(props) {
    super(props);
  }

  ...


  render(){
    return(
      <SafeAreaView style={styles.container}>
        <Button onPress={() => setFreunde(2)}/>
          ...
      </SafeAreaView>
    );
  }
}

const styles = StyleSheet.create({
  ...
});

const mapDispatchToProps = (dispatch, ownProps) => ({
  setFreunde: () => {
    const { value } = ownProps
    dispatch(setFreunde(value))
  },
  setChats: () => {
    const { value } = ownProps
    dispatch(setChats(value))
  },
  setVotes: () => {
    const { value } = ownProps
    dispatch(setVotes(value))
  }
})

export default connect( null, mapDispatchToProps )(NavStack)

If I log the setFreunde(2) the console says the following:

Object { "type": "SET_FREUNDE", "value": 2, }

However, the value does not change which I retrieve in my App.tsx as follows:

const counterfreunde = useSelector((state)=>state.counterfreunde);

What is my mistake?

Upvotes: 0

Views: 117

Answers (1)

Linda Paiste
Linda Paiste

Reputation: 42160

Problem: Not Dispatching Action

<Button onPress={() => setFreunde(2)}/>

This code right here is just calling the action creator setFreunde. It does not dispatch it.

Your mapDispatchToProps function adds a prop setFreunde to your component which takes no arguments and dispatches the action with the value from props.value. You are not using this prop. You are just using the action creator. You need to call the function from props:

<Button onPress={this.props.setFreunde} title="Set Freunde" />

That fixes the functionality. You do need to add a lot of annotations if you are trying to use typescript here. It's easier with function components!

import { createStore } from "redux";
import { Provider, connect } from "react-redux";
import React, { Dispatch } from "react";
import { SafeAreaView, Button, Text } from "react-native";

const SET_FREUNDE = "SET_FREUNDE";
const SET_CHATS = "SET_CHATS";
const SET_VOTES = "SET_VOTES";

export function setFreunde(value: number) {
  return {
    type: SET_FREUNDE,
    value
  };
}

export function setChats(value: number) {
  return {
    type: SET_CHATS,
    value
  };
}

export function setVotes(value: number) {
  return {
    type: SET_VOTES,
    value
  };
}

const defaults = {
  countervotes: 2,
  counterchats: 1,
  counterfreunde: 1
};

type State = typeof defaults;

type Action = ReturnType<typeof setVotes | typeof setChats | typeof setFreunde>;

function counter(state: State = defaults, action: Action): State {
  switch (action.type) {
    case SET_FREUNDE:
      return { ...state, counterfreunde: action.value };
    case SET_CHATS:
      return { ...state, counterchats: action.value };
    case SET_VOTES:
      return { ...state, countervotes: action.value };
    default: {
      return state;
    }
  }
}

const store = createStore(counter);

const mapDispatchToProps = (
  dispatch: Dispatch<Action>,
  ownProps: OwnProps
) => ({
  setFreunde: () => {
    const { value } = ownProps;
    dispatch(setFreunde(value));
  },
  setChats: () => {
    const { value } = ownProps;
    dispatch(setChats(value));
  },
  setVotes: () => {
    const { value } = ownProps;
    dispatch(setVotes(value));
  }
});

const mapStateToProps = (state: State) => ({
  freund: state.counterfreunde
});

interface OwnProps {
  value: number;
}

type Props = OwnProps &
  ReturnType<typeof mapDispatchToProps> &
  ReturnType<typeof mapStateToProps>;

class NavStack extends React.Component<Props> {
  render() {
    return (
      <SafeAreaView>
        <Text>Freunde Value: {this.props.freund}</Text>
        <Button onPress={this.props.setFreunde} title="Set Freunde" />
      </SafeAreaView>
    );
  }
}

const Test = connect(mapStateToProps, mapDispatchToProps)(NavStack);

export default function App() {
  return (
    <Provider store={store}>
      <Test value={5} />
    </Provider>
  );
}

Code Sandbox Demo

Upvotes: 1

Related Questions