React Redux: Difference between revisions

From bibbleWiki
Jump to navigation Jump to search
No edit summary
Line 16: Line 16:


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


Line 22: Line 24:
var state2 = Object.assign({}, state, {point:50})
var state2 = Object.assign({}, state, {point:50})
</syntaxhighlight>
</syntaxhighlight>
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=
=Example=

Revision as of 02:26, 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>        )
    }
}

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