0
votes

I'm trying to implement redux to show balance in multiple screens as I update balance in single screen it should reflect in all other screens/components.

I'm pretty new to redux. As you know with complexity around redux, its even making difficult to implement it.

I followed some examples in GitHub and youtube and started implementing it .

Under Actions folder I have. following two files

counteractions.js

import * as types from './actionTypes.js';

//ActionCreator methods

export function updateBalance(balanceInfo) {

    return {
        type: types.LEDGER_BALANCE,
        payLoad: { balanceInfo }
    }
}

Under Reducers folder.I have this file

balance.js

import * as types from '../actions/actionTypes.js';

const initialState = {
    balance: 0
}

// reducer  functions .. accepts  current/initial state , actions and  returns new state

const balanceReducer=(state,action)=>
{
    switch (action.type) {
        case types.LEDGER_BALANCE:
            return {
                balance: action.payload.balanceInfo
            }
            break;
        default:
            break;
    }
}

export default balanceReducer;

in ConfigureStore.js

import {createStore} from 'redux'; import rootReducer from './reducers/index.js';

import balanceReducer from './reducers/balance.js';

const initailState = {
    balance: 0,
}

export const store=createStore(balanceReducer,balanceReducer);

App.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import { Provider } from 'react-redux';
//Provider - makes redux store  available to connect() class in component hierarchy below
import { applyMiddleware, createStore, compose, combineReducers } from "redux";
import thunkMiddleware from 'redux-thunk';
import createLogger from 'redux-logger';
import rootReducer from './reducers/index.js';
//import store from './configureStore.js';

import {
  Platform,
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  TextInput
} from 'react-native';
import ReduxDemo from "./reduxDemo.js";
import { store, reducer } from './balanceDemo.js';

const instructions = Platform.select({
  ios: 'Press Cmd+R to reload,\n' +
  'Cmd+D or shake for dev menu',
  android: 'Double tap R on your keyboard to reload,\n' +
  'Shake or press menu button for dev menu',
});

export default class App extends Component<{}> {

  constructor(props) {
    super(props);
    this.state = {
      balancelocal: '',
    }
  }



  _updateLedger = () => {
    // store.dispatch({ type: 'BALANCE', payLoad: '500' });
    store.dispatch({ type: 'BALANCE', payLoad: 'Your balance is 8000 MUR' });
  }


  render() {

    store.subscribe(() => {

      this.setState({
        balancelocal: store.getState(),
      })
      //this.balanceInfo = store.getState().balance;
     // alert(this.state.balancelocal);
    });
    return (
      <View style={styles.container}>
        <TouchableOpacity onPress={this._updateLedger}>
          <Text>Update balance</Text>
        </TouchableOpacity>

        <TextInput style={{height:100,width:400}} value={this.state.balancelocal}/>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

I'm yet to complete configure store file. and. I'm wondering. where I have to subscribe and dispatch actions ..

I want to update balance with button click from app.js I have. to update balance in another page automatically..

Please guide me to understand and implement redux .Please suggest better folder structure and better way to implement redux.

1

1 Answers

0
votes

There is quite a bit here to understand.

The basic workflow is (you can have the receiving component as a different one)

Component Button > Action > Reducer > Component Props > Render

To achieve this you need both the setup of the store and the invoking of the "event" through redux.

Below is an example (excuse if not perfect, just typed into here), but the way the other component gets the value from the action is becuase it uses the 'connect' HOC. Everytime redux gets a state change it calls all components that are 'connected'. Here we take the updated balance and return it as part of the 'mapStateToProps' function, which is just setting the components props with that object. The balance is then accessed via this.props.balance and displayed.

This becomes more useful if you want to either call an api in the action and store the result in the reducer. All connected components will then get that new data.

Note1: I have only used redux-thunk middleware to dispatch so forgive me for using that.

Note2: This is a simple example. When the app gets better you will need to prevent over-rendering since any reducer changes will invoke all connected components. I use reselect here.

Setup

reducers.js

import { combineReducers } from 'redux';
import { balanceReducer } from 'balanceReducer';
export default combineReducers({
    balanceReducer
})

store.js

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk'

import combineReducers from './reducers'

export default function configureStore() {
  let store = createStore(combineReducers, applyMiddleware(thunk));
  return store;
}

index.js

import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
import { Provider } from 'react-redux';

import configureStore from './store';
import Component1 from './component1';

const store = configureStore()

const myapp = () => (
  <Provider store={store}>
    <View>
        <Component1 />
    <View>
  </Provider>
)

AppRegistry.registerComponent('myapp', () => myapp);

Components

component1.js (key part is the connect HOC)

import { connect } from 'react-redux';
import React, { Component } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';  
import { updateBalance } from './action';

class Component1 extends Component {

    _updateLedger = () => {
        this.props.updateBalance(500);
    }
    render() {
       const { balance } = this.props;
       return (
          <View>
            <TouchableOpacity onPress={this._updateLedger}>
              <Text>Update balance</Text>
            </TouchableOpacity>
            <Text>{balance}</Text>
          </View>
       )
    }
}

function mapStateToProps(state) {
   return {
       balance: state.balanceReducer.balance
   }
}

function mapDispatchToProps(dispatch) {
  return {
      updateBalance = (balanceInfo) => dispatch(updateBalance(balanceInfo))
  };
}

export default connect(
  mapStatetoProps,
  mapDispatchToProps
)(Component1)

action.js

export function updateBalance(balanceInfo) {

    return {
        type: types.LEDGER_BALANCE,
        payLoad: { balanceInfo }
    }
}

balanceReducer.js (key part here is to return new state)

const initialState = {
    balance: 0,
}
export function balanceReducer(state = initialState, action) {
   if(action.type === types.LEDGER_BALANCE) {
      return {
          balance: action.payLoad.balanceInfo
      }
   }
}