A
A
Alexander Kusak2017-05-23 20:06:49
React Native
Alexander Kusak, 2017-05-23 20:06:49

Why is dispatch not working in ReactNative?

I'm asking for help, I'm writing a ReactNative application using Redux, I'm trying to make a similar structure as a ReactJS web application, but jambs appear due to which Redux does not work at all.
The structure of the application is as follows:
RLWrAO.png

app.js
import React, { Component } from 'react';
import { createStore, combineReducers } from 'redux'
import { View } from 'react-native';
import { Provider, connect } from 'react-redux';
import Root from './containers/Root';
import reducer from './reducers';
import styles from './styles';

let store = createStore(reducer);

export default class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <Root />
      </Provider>
    );
  }
}

Reducers.js
import { combineReducers } from 'redux'
import counter from './reducers/counter';
import login from './reducers/login';

export default combineReducers({
  counter,
  login
});

reducers/counter.js
//import { createStore } from 'redux'

const initState = {
  num: 0
};

export default function counter(state = initState, action) {
  switch (action.type) {
    case 'COUNTER:INCR':
      console.log('INCREMENT');
      state.num = state.num++;
      return state;
    case 'COUNTER:DECR':
      console.log('DECREMENT');
      state.num = state.num--;
      return state;
    case 'COUNTER:RES':
      state.num = 0;
      return state;
    default:
      return state;
  }
}

containers/Root.js
import React, { Component } from 'react';
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux';
import { Button, Text, View } from 'react-native';

import CounterContainer from './CounterContainer.js';

import styles from '../styles';


class Root extends Component {
  render() {
    return (
        <View style={styles.container}>
            <CounterContainer/>
        </View>
    );
  }
}

export default connect(
  state => ({
    count: state
  }), 
  (dispatch) => ({
    increment: () => { dispatch({ type: 'INCREMENT' }) },
    decrement: () => { dispatch({ type: 'DECREMENT' }) },
    reset: () => { dispatch({ type: 'RESET' }) },
  }))(Root)

containers/CounterContainer.js
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { View } from 'react-native';
import Counter from '../components/Counter';

export default class CounterContainer extends Component {
  render() {
    return (
        <View style={styles.container}>
            <Counter />
        </View>
    );
  }
}

components/Counter.js
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Button, Text, View } from 'react-native';

import styles from '../styles';

class Counter extends Component {
  
  render() {
    return (
      <View>
        <Button title='UP' onPress={this.props.increment} />
        <Text style={styles.counter} onPress={this.props.reset}>
           { this.props.state.num }
        </Text>
        <Button title='DOWN' onPress={this.props.decrement} />
      </View>
    );
  }

}

export default connect(
  state => ({
    state: state.counter
  }), 
  dispatch => ({
    increment: (number) => { dispatch({ type: 'COUNTER:INCR', number }) },
    decrement: (number) => { dispatch({ type: 'COUNTER:DECR', number }) },
    reset: () => { dispatch({ type: 'COUNTER:RES' }) },
  }))(Counter)


I started writing it from this project: Link (poking)
But it is sharpened only for one screen and a reducer.
I'm currently getting an error on a real device with the text:
does not support changing `store` on the fly. It's most likely ...
Any help needed as I need to fully understand how Redux works on ReactNative. Thanks in advance!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
O
Oleg Drapeza, 2017-05-24
@McFree

It looks like the problem is not in React Native:

export default function counter(state = initState, action) {
  switch (action.type) {
    case 'COUNTER:INCR':
      console.log('INCREMENT');
      state.num = state.num++;
      return state;
    case 'COUNTER:DECR':
      console.log('DECREMENT');
      state.num = state.num--;
      return state;
    case 'COUNTER:RES':
      state.num = 0;
      return state;
    default:
      return state;
  }
}

You need to familiarize yourself with the principles of Redux. You cannot change the store, the argument statein the reducer gets storeyour application, and in each case block you must return either the unmodified store (default) or a copy of your store:
export default function counter(state = initState, action) {
  switch (action.type) {
    case 'COUNTER:INCR':
      return {
        ...state,
        num: state.num + 1
      };
    case 'COUNTER:DECR':
      return {
        ...state,
        num: state.num - 1
      };
    case 'COUNTER:RES':
      return {
        ...state,
        num: 0
      };
    default:
      return state;
  }
}

Instead of the spread operator
{
  ...state,
  num: state.num + 1
}

can be used
Object.assign({}, state, { num: state.num + 1 })

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question