React Redux: Difference between revisions

From bibbleWiki
Jump to navigation Jump to search
Line 88: Line 88:
}
}
</syntaxhighlight>
</syntaxhighlight>
=Reducer=
== Rules ==
Reducer must not
* Mutate arguments
* Perform side effects
* Call non-pure functions
Pure function are those where the answer is predictable and the same every time e.g.
<syntaxhighlight lang="javascript">
function add(a, b) {
  return a + b;
}
</syntaxhighlight>
== Example of reducer ==
Here is a reducer which is wrong because it changes the original state
<syntaxhighlight lang="javascript">
function myReducer(stat, action) {
    switch(action.type) {
        case "INCREMENT_COUNT":
          state.counter++
          return state
        default:
          return state
    }
</syntaxhighlight>
The above is wrong because the state is change. Here is the corrected version
<syntaxhighlight lang="javascript">
function myReducer(stat, action) {
    switch(action.type) {
        case "INCREMENT_COUNT":
          return { ...state, counter: state.count + 1}
        default:
          return state
    }
</syntaxhighlight>


=Example Component with provider=
=Example Component with provider=
This removes the need to subscribe and pass the original amount
This removes the need to subscribe and pass the original amount


<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
Line 97: Line 138:


     render() {
     render() {
         return (
         return (
           <div>
           <div>

Revision as of 02:39, 2 June 2020

Unidirectional

Data only flows one direction

Pure Functions

  • Like static is c#/c++ only using inputs to produce outputs
 function multiply(a, b)
 {
   return a * b;
 }
  • No side effects
  • Also yields same result

Immutability

== Way to be immutable ES6 allows us to copy objects using Object.assign e.g.

var state = {color:'red', name: 'Adam', point:5}
var state2 = Object.assign({}, state, {point:50})

You can use map or filter, reduce, concat or spread as these all create a new object

Tools to enforce immutability

  • Using trust with your team - relies on good code reviews
  • Use redux-immutable-state-invarient a package to detect problems (not for prod)
  • Enforce by using products like Immer, Immutable.js etc

Example

Note ... is new syntax for spread

Stores often are stored in stores/configurationStore.js at the same level as compontents

import {createStore} from 'redux'

var defaultState = {
    originalAmount: 0.00
};

function amount(state = defaultState, action) {
    if(action == = 'CHANGE_ORIGIN_AMOUNT') {
        return {
            ...state,
            originalAmount: action.data
        }
        // return Object.assign({},state, {originalAmout: action.data})
    }
}

var store = createStore();

store.subscribe(function() {
    console.log('state', store.getState());
})

store.dispatch({type:'CHANGE_ORIGIN_AMOUNT', data: 30.00});
store.dispatch({type:'', data: 30.00});
store.dispatch({type:'', data: 30.00});

Example Component

Show us subscribing to the store to make sure updates passed down to the components.

class MainConponent extends React.Component {

    componentDidMount() {
        store.subscribe( () => {
            this.setState({});
        } )
    }

    render() {
        return (
           <div>
               <Conversion originalAmount={store.getState().originalAmount} />
           </div>        )
    }
}

Reducer

Rules

Reducer must not

  • Mutate arguments
  • Perform side effects
  • Call non-pure functions

Pure function are those where the answer is predictable and the same every time e.g.

function add(a, b) {
   return a + b;
}

Example of reducer

Here is a reducer which is wrong because it changes the original state

function myReducer(stat, action) {
    switch(action.type) {
        case "INCREMENT_COUNT":
           state.counter++
           return state 
        default:
           return state 
    }

The above is wrong because the state is change. Here is the corrected version

function myReducer(stat, action) {
    switch(action.type) {
        case "INCREMENT_COUNT":
           return { ...state, counter: state.count + 1}
        default:
           return state 
    }


Example Component with provider

This removes the need to subscribe and pass the original amount


class MainConponent extends React.Component {

    render() {

        return (
           <div>
               <Conversion/>
           </div>        )
    }
}

ReactDOM.render(<Provide store={store}><MainComponent /></Provider>,getElementById('container'));

We need to map the state back to the properties on initialisation of the component. We do this via connect

export default connect(function mapStateToProps(state,props)) {

    return {
        originAmount : state.originalAmount
    }
}

Adding logging to redux

This will show action prev state and next state

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

var store = createStore(
    amount,
    applyMidddleware(logger)
);

Setting types using keyMirror

Just a nice little tip. keyMirror stops you having to type more for const e.g.

export var ActionType = {
    const THIS_IS_A_CONST = "THIS_IS_A_CONST";
};

becomes

export var ActionType = keyMirror ({
    THIS_IS_A_CONST = null
});

Example on Git hub

You can find an example at [[1]]

how it works

In the code handleOriginalAmount is fired by a change

    this.props.dispatch(actions.changeOriginAmount(newAmount));

In the store there is a reducer which has the actions

function amount(state = defaultState, action) {
    switch (action.type) {
        case (types.CHANGE_ORIGIN_AMOUNT):
            return {
                ...state,
                originAmount: action.data.newAmount
           }
        case (types.CHANGE_DESTINATION_AMOUNT):
            return {
                ...state,
                destinationAmount: action.data.newAmount
           }
        case (types.CHANGE_ORIGIN_CURRENCY):
            return {
                ...state,
                originCurrency: action.data.newCurrency
            }


Here is an example of an action

export function changeOriginAmount(newAmount) {
  return {
    type:types.CHANGE_ORIGIN_AMOUNT,
    data:{newAmount: newAmount}
  }
}

Because the page is connected to redux via the connect when state changes the properties change

export default connect((state, props) => {
    return {
        originAmount: state.amount.originAmount,
        destinationAmount: state.amount.destinationAmount,
        originCurrency: state.amount.originCurrency,
        destinationCurrency: state.amount.destinationCurrency,
        conversionRate: state.amount.conversionRate,
        feeAmount: state.amount.feeAmount,
        totalCost: state.amount.totalCost,
        errorMsg: state.error.errorMsg
    }

})(Conversion);