0
votes

Summary

In order to learn Redux, I am incorporating some state, actions, reducers, and trying to see how they are used in React Components. I have set up a test object...

const initialState = {
    navigationCount : 0,
    someNumber      : 500,
    someList        : ['aa',22,'c5d6','45615'],
};

...and aim to:

  • increment the navigationCount by 1 when visiting pages

  • add or subtract from someNumber

  • push() & pop() elements from someList.

Versions

Currently using gatsby ^2.5.0, react ^16.8.6, and react-redux ^6.0.1.

Code

actions & reducers

import { combineReducers } from 'redux';
import {
    PAGE_INCREMENT,
    NUMBER_INCREASE,
    NUMBER_DECREASE,
    LIST_PUSH,
    LIST_POP,
} from './actionTypes.js';

// state
const initialState = {
    navigationCount : 0,
    someNumber      : 500,
    someList        : ['aa',22,'c5d6','45615'],
};

// action creators returning actions
export const pageIncrementer = navigationCount => {
    return {
        type: PAGE_INCREMENT,
        navigationCount,
    };
};
export const numberAdder = numberToAdd => {
    return {
        type: NUMBER_INCREASE,
        numberToAdd,
    };
};
export const numberMinuser = numberToMinus => {
    return {
        type: NUMBER_DECREASE,
        numberToMinus,
    };
};
export const listPusher = itemToAdd => {
    return {
        type: LIST_PUSH,
        itemToAdd,
    }
};
export const listPopper = () => {
    return {
        type: LIST_POP,
    }
};

// reducers
const pageIncrementReducer = (state = initialState, action) => {
    switch (action.type) {
        case PAGE_INCREMENT:
            return Object.assign({}, ...state, {
                navigationCount: action.navigationCount+1
            });
        default:
            return state.navigationCount;
    }
};
const numberChanger = (state = initialState, action) => {
    switch (action.type) {
        case NUMBER_INCREASE:
            return Object.assign({}, ...state, {
                someNumber: state.someNumber+action.numberToAdd,
            });
        case NUMBER_DECREASE:
            return Object.assign({}, ...state, {
                someNumber: state.someNumber-action.numberToMinus,
            });
        default:
            return state.someNumber;
    };
};
const listChanger = (state = initialState, action) => {
    switch (action.type) {
        case LIST_POP:
            return Object.assign({}, ...state, {
                someList: state.someList.pop(),
            });
        case LIST_PUSH:
            return Object.assign({}, ...state, {
                someList: state.someList.push(action.itemToAdd),
            });
        default:
            return state.someList;
    }
}

// store
const rootReducer = combineReducers({
    pageIncrementReducer,
    numberChanger,
    listChanger,
});

export default rootReducer;

React Component

import React from 'react';
import Layout from '../components/common/Layout.jsx';
import LandingBanner from '../components/landing/LandingBanner.jsx';
import LandingNavgrid from '../components/landing/LandingNavgrid.jsx';
import LandingApp from '../components/landing/LandingApp.jsx';

import { connect } from 'react-redux';
import {
    PAGE_INCREMENT,
    NUMBER_INCREASE,
    NUMBER_DECREASE,
    LIST_PUSH,
    LIST_POP,
} from '../state/actionTypes';

class LandingPage extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            appliedNum: 2000,
        };
    }

    componentDidMount(){
        // this.props.pageIncrement(); // => numberChanger returned undefined
        // this.props.numberIncrease(4444); // => pageIncrementReducer returned undefined
        // this.props.numberDecrease(4444); // => pageIncrementReducer returned undefined
        // this.props.listPush(4444); // => pageIncrementReducer returned undefined
        this.props.listPop();
    }

    render(){
        return (
            <Layout>
                <LandingBanner/>
                <LandingNavgrid/>
                <LandingApp/>
            </Layout>
        )
    }
}

const filterNumbers = (list=[]) => {
    console.log('filterNumbers list: ', list);
    return list.filter(listElement => !!Number(listElement));
};
const mapStateToProps = (state, ownProps) => {
    return {
        someNumber: state.someNumber,
        someList: filterNumbers(state.someList),
        navigationCount: state.navigationCount,
    };
};

const mapDispatchToProps = (dispatch) => {
    return {
        pageIncrement: () => dispatch({ type: PAGE_INCREMENT }),
        numberIncrease: () => dispatch({ type: NUMBER_INCREASE }),
        numberDecrease: () => dispatch({ type: NUMBER_DECREASE }),
        listPush: () => dispatch({ type: LIST_PUSH }),
        listPop: () => dispatch({ type: LIST_POP }),
    }
}

export default connect(
    mapStateToProps,
    mapDispatchToProps,
)(LandingPage);

Errors

redux.js:449 Uncaught Error: Given action "LIST_POP", reducer "pageIncrementReducer" returned undefined. To ignore an action, you must explicitly return the previous state. If you want this reducer to hold no value, you can return null instead of undefined.

1

1 Answers

0
votes

first of all, you always need to return state on the default switch case.

default:
       return state;