CameronBurkholder
CameronBurkholder

Reputation: 842

Why is my ReactRedux.connect statement not working?

I am writing a calculator app as a project for FreeCodeCamp. I have decided to write it using React and Redux. I've written the Redux part of the app, and I started to connect Redux to React.

When I wrote all the code to connect Redux to my React app, the rendering stopped working. I used different console.log() statements to track down where the JavaScript was choking, and I narrowed it down to the connect statement found on line 241 of the linked Codepen. If you comment out line 242, and replace line 255 with ReactDOM.render(<Calculator/>, wrapper); the app renders. However, the same code running on FreeCodeCamp's platform appears to work.

Here is the link to my CodePen: JavaScript Calculator.

The challenge I used on FreeCodeCamp to test my code can be found here: FCC Challenge

The exact code I adapted from FCC (in order to get the editor to render my component) is below. You can see the changes I made from the Pen are only in the rendering part of the code.

const wrapper = document.querySelector("#wrapper");

// REDUX
const initialState = {
  operation: "",
  lastResult: "",
  operand: "",
  lastInput: "",
  display: "0"
}
const operators = ["+", "-", "*", "/"];
const ADD_DIGIT = "ADD_DIGIT";
const ADD_OPERATOR = "ADD_OPERATOR";
const ADD_DECIMAL = "ADD_DECIMAL";
const CLEAR = "CLEAR";
const EVALUATE = "EVALUATE";
const { createStore } = "Redux";

function reducer(state = initialState, action) {
  let newState;
  switch (action.type) {
    case ADD_DIGIT:
      // Number can't begin with multiple zeros, leave state the way it is
      if (state.lastInput === "0" && action.value === "0") {
        newState = state;
      // If last operation was =, start new operation
      } else if (state.lastInput === "=") {
        let newOperation = "" + action.value;
        newState = {
          operation: "",
          lastResult: state.lastResult,
          operand: newOperation,
          lastInput: action.value,
          display: newOperation
        }
      // If previous input was an operator, add operator to operation, reset display and start adding digits
      } else if (operators.indexOf(state.lastInput) > -1) {
        let newOperation = "" + action.value;
        newState = {
          operation: state.operation += state.lastInput,
          lastResult: state.lastResult,
          operand: newOperation,
          lastInput: action.value,
          display: newOperation
        }
      // Else, add digit to the current operand and display value
      } else {
        /* Append digit to operand, add to lastInput */
        /* Add digit to display */
        newState = {
          operation: state.operation,
          lastResult: state.lastResult,
          operand: state.operand + action.value,
          lastInput: action.value,
          display: state.display + action.value
        }
      }
      break;

    case ADD_OPERATOR:
      // Operation can't begin with operator unless previous operation was =
      if (state.operation === "") {
        if (state.lastInput === action.value) {
          newState = {
            operation: state.operation,
            lastResult: state.lastResult,
            operand: state.lastResult + "" + action.value,
            lastInput: action.value,
            display: state.lastResult + "" + action.value
          }
        } else {
          newState = state;
        }
      // If 2 or more operators are entered consecutively, use the most recently entered
      } else if (operators.indexOf(state.lastInput) > -1) {
        newState = {
          operation: state.operation,
          lastResult: state.lastResult,
          operand: "",
          lastInput: action.value,
          display: action.value
        }
      // Input should be handled normally for operator
      } else {
        /* Add current operand to operation */
        /* Set valid operator to lastInput */
        /* Add operator to display */
        newState = {
          operation: state.operation + state.operand,
          lastResult: state.lastResult,
          operand: "",
          lastInput: action.value,
          display: action.value
        }
      }
      break;

    case ADD_DECIMAL:
      // If used to begin a number, prepend a 0
      if (state.operand === "") {
        let newOperation = "0" + action.value;
        newState = {
          operation: state.operation,
          lastResult: state.lastResult,
          operand: newOperation,
          lastInput: action.value,
          display: newOperation
        }
      // No two decimals in one number
      } else if (state.operand.split("").indexOf(action.value) > -1 || state.lastInput === action.value) {
        newState = state;
      } else {
        /* Append decimal to lastInput, operand */
        /* Add decimal to display */
        newState = {
          operation: state.operation,
          lastResult: state.lastResult,
          operand: state.operand + action.value,
          lastInput: action.value,
          display: state.display + action.value
        }
      }
      break;   

    case EVALUATE:
      // Operation can't end with an operator
      // If input is only one operand, return that
      // Otherwise each operator must include two operands    
      if (operators.indexOf(state.lastInput) < 0) {
        /* Evalue the result of operand (Using eval() ) */
        /* Add result to display */
        /* Store result in lastResult, clear other state props */
        let result = eval(state.operation);
        newState = {
          operation: "",
          lastResult: result,
          operand: "",
          lastInput: action.value,
          display: result
        }
      }
      break;

    case CLEAR:
      /* Clear state, input, and display */
      newState = initialState;
      break;

    default:
      newState = state;
      break;
  }

  return newState;
}

function addDigit(digit) {
  let action = {
    type: ADD_DIGIT,
    value: digit
  }
  return action;
}
function addOperator(operator) {
  let action = {
    type: ADD_OPERATOR,
    value: operator
  }
  return action;
}
function addDecimal() {
  let action = {
    type: ADD_DECIMAL,
    value: "."
  }
  return action;
}
function evaluate() {
  let action = {
    type: EVALUATE,
    value: "="
  }
  return action;
}
function clear() {
  let action = {
    type: CLEAR,
    value: ""
  }
  return action;
}

const store = Redux.createStore(reducer);



// REACT-REDUX
const mapStateToProps = function(state) {
  console.log("map state to props");
  return {
    display: state.display
  }
}
const mapDispatchToProps = function(dispatch) {
  console.log("map dispatch to props");
  return {
    calcAddDigit: function(digit) {
      dispatch(addDigit(digit));
    },
    calcAddOperator: function(operator) {
      dispatch(addOperator(operator));
    },
    calcAddDecimal: function() {
      dispatch(addDecimal());
    },
    calcEvaluate: function() {
      dispatch(evaluate());
    },
    calcClear: function() {
      dispatch(clear());
    }
  }
}
const Provider = ReactRedux.Provider;
const connect = ReactRedux.connect;



// REACT
class Calculator extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return(
      <h1>Functioning</h1>
    )
  }
}

console.log("before connect statement - line 241");
Calculator = connect(mapStateToProps, mapDispatchToProps)(Calculator);
console.log("after connect statement");

class CalculatorApp extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <Provider store={store}>
        <Calculator/>
      </Provider>
    );
  }
}

class AppWrapper extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <Calculator/>
      </Provider>
    );
  }
};

Upvotes: 1

Views: 130

Answers (1)

marzelin
marzelin

Reputation: 11600

Because the order in which you import external scripts matters. Put redux below react because react-redux requires React to be present in the global scope.

Correct order is:

  1. react
  2. react-dom
  3. redux
  4. react-redux

Upvotes: 1

Related Questions