Help with calculator project number displaying

Hello! I’m struggling with the calculator project and after many hours trying to fix it I really don’t understand what’s going on. Currently I have a numpad, an operators pad and two displays: one for showing the current input and the other to display the operation and will in the end display the output after evaluating. Codepen link

For easier understanding:

Components:

Components
const Display = (props) => {
    return (
        <div>
            <div id="display" style={{ width: "400px", border: "1px solid red", height: "50px" }}>
                {props.input}
            </div>
            <div id="display-output" style={{ width: "400px", border: "1px solid green", height: "50px" }}>
                {props.output}
            </div>
        </div>
    )

}

const NumPad = (props) => {
    function handleNumPadClick(e) {
        if (e.target.value == ".") {
            props.addNewDecimal(e.target.value)
        } else if (e.target.value == "0") {
            props.addNewZero(e.target.value)
        } else if (props.input.length == 1) {
            props.addFirstNumber_dispatched(e.target.value)
        } else {
            props.addNewNumber(e.target.value)
        }
    }
    return (
        <div onClick={handleNumPadClick} style={{ width: "400px", border: "1px solid green", height: "50px" }}>
            <button id="one" value="1">1</button>
            <button id="two" value="2">2</button>
            <button id="zero" value="0">0</button>
            <button id="decimal" value=".">.</button>
        </div>
    )
}

const Operators = (props) => {
    function handleOperatorsClick(e) {
        props.addNewOperator(e.target.value)
    }
    return (
        <div onClick={handleOperatorsClick} style={{ width: "400px", border: "1px solid blue", height: "50px" }}>
            <button id="add" value="+">+</button>
        </div>
    )
}

class Presentational extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <div>
                <Display input={this.props.input} output={this.props.output} />
                <NumPad input={this.props.input} addFirstNumber_dispatched={this.props.addFirstNumber_dispatched} addNewNumber={this.props.addNewNumber} addNewDecimal={this.props.addNewDecimal} addNewZero={this.props.addNewZero} />
                <Operators addNewOperator={this.props.addNewOperator} />
            </div>
        )
    }
}

Action creators: one for adding new number so it replaces the initial 0, two for 0 and . each,one for adding normal numbers and a last one for operators.

Action creators
const FIRST_NUMBER = 'FIRST_NUMBER'
const ADD_NUMBER = 'ADD_NUMBER'
const ADD_DECIMAL = 'ADD_DECIMAL'
const ADD_ZERO = 'ADD_ZERO'
const ADD_OPERATOR = 'ADD_OPERATOR'

//ACTION CREATOR
const addFirstNumber = (number) => {
    return {
        type: FIRST_NUMBER,
        number: number
    }
}

const addNumber = (number) => {
    return {
        type: ADD_NUMBER,
        number: number
    }
}

const addDecimal = () => {
    return {
        type: ADD_DECIMAL
    }
}

const addZero = (number) => {
    return {
        type: ADD_ZERO,
        number: number
    }
}

const addOperator = (operator) => {
    return {
        type: ADD_OPERATOR,
        operator: operator
    }
}

Reducers, one for input the other one for output:

Reducers
var contains_decimal = (/\./)

const inputReducer = (state = '0', action) => {
    switch (action.type) {
        case FIRST_NUMBER:
            return eval(parseInt(state + action.number))
        case ADD_NUMBER:
            return state + action.number
        case ADD_DECIMAL:
            if (contains_decimal.test(state)) {
                return state
            }
            return state + '.'
        case ADD_ZERO:
            if (contains_decimal.test(state) || state != "0") {
                return state + "0"
            }
            return state
        case ADD_OPERATOR:
            return action.operator
        default:
            return state
    }
}

const outputReducer = (state = '', action) => {
    switch (action.type) {
        case FIRST_NUMBER:
            return eval(parseInt(state + action.number))
        case ADD_NUMBER:
            return state + action.number
        case ADD_DECIMAL:
            if (contains_decimal.test(state)) {
                return state
            }
            return state + '.'
        case ADD_ZERO:
            if (contains_decimal.test(state) || state != "0") {
                return state + "0"
            }
            return state
        case ADD_OPERATOR:
            return state + action.operator
        default:
            return state
    }
}

And mapping:

Mapping
function mapStateToProps(state) {
    return ({
        input: state.input,
        output: state.output
    })
}

function mapDispatchToProps(dispatch) {
    return ({
        addFirstNumber_dispatched: (number) => {
            dispatch(addFirstNumber(number))
        },
        addNewNumber: (number) => {
            dispatch(addNumber(number))
        },
        addNewDecimal: () => {
            dispatch(addDecimal())
        },
        addNewZero: (number) => {
            dispatch(addZero(number))
        },
        addNewOperator: (operator) => {
            dispatch(addOperator(operator))
        }
    })
}

I ignored the connection and other stuff because I’m sure that works. But everything’s on the codepen.

The problem comes when I add an operator after a number and then another one but the operator gets replaced in the output, I really don’t have a clue why this is happening. This behavior doesn’t seem to occur when there’s a 0 after the operator but once I input a +[any_other_number] everything from the first operator gets replaced.

I know it’s a lot but any help would be greatly appreciated.

I’m new to React and don’t know Redux at all but it seems to me that it’s within the “first number” logic. This caught my eye:

case FIRST_NUMBER: return eval(parseInt(state + action.number))

Is that removing the operator?
-J

1 Like

Yes! After posting I think there’s the issue because once a + gets displayed in the input display the length is 1 and for the next button pressed the FIRST_NUMBER action gets called. I really should think a way to avoid recurring to the length stuff or a better way to replace the damn first zero in the display input. Thanks m8.

1 Like