McFree
@McFree
JS, TS, C#

Почему не работает dispatch в ReactNative?

Прошу о помощи, пишу приложение на ReactNative с использованием Redux, стараюсь сделать аналогичную структуру как и у веб приложения на ReactJS но появляются косяки из-за которых не работает Redux вообще.
Структура приложения такова:
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)



Начинал его писать от этого проекта: Ссылка(тыкабельно)

Но он заточен лишь на один экран и редьюсер.
В данный момент у меня появляется ошибка на реальном устройстве с текстом:
does not support changing `store` on the fly. It most likely ...

Нужна любая помощь так как необходимо полностью разобраться с работой Redux на ReactNative. Заранее Спасибо!
  • Вопрос задан
  • 296 просмотров
Решения вопроса 1
@SuperOleg39ru
Front-end разработчик
Похоже проблема не в 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;
  }
}


Вам нужно ознакомиться с принципами Redux. Нельзя изменять хранилище, аргумент state в редьюсере получает store вашего приложения, а в каждом блоке case вы должны возвращать либо не измененный store (default), либо копию вашего хранилища:

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;
  }
}


Вместо spread оператора

{
  ...state,
  num: state.num + 1
}

можно использовать
Object.assign({}, state, { num: state.num + 1 })
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы