The action takes an attribute from the class component but does not enter the Reducer-React

Asked

Viewed 468 times

2

I’m doing a simple project with React and Redux to train and pick up an attribute (string) that is in the store through a component function I do a processing in this string and send to action that should send to Reset and save it in a store attribute. However this string reaches the action but does not enter the Return, what may be wrong? Codes below.

Component:

import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

import { msgChanged, resultChanged, clear } from '../actions/messageAction';

import Button from './button';

class Message extends Component {
constructor(props) {
    super(props);
    this.encrypt = this.encrypt.bind(this);
    this.decrypt = this.decrypt.bind(this);
}

encrypt() {
    let step = this.props.counter.step;
    let msg = this.props.message.msg.toUpperCase();
    let alpha = this.props.message.alpha;
    let resultAux = '';
    for(let j = 0; j < msg.length; j++) {
        if(msg[j] === ' ') {
            resultAux += ' ';
        } else {
            for (let i = 0; i < alpha.length; i++) {
                if(msg[j] === alpha[i]) {
                    let num = (i + step) % alpha.length
                    resultAux += alpha[num];
                }
            }
        }
    }
    resultChanged(resultAux);
}

decrypt() {
    let step = this.props.counter.step;
    let msg = this.props.message.msg.toUpperCase();
    let alpha = this.props.message.alpha;
    let resultAux = '';
    for(let j = 0; j < msg.length; j++) {
        if(msg[j] === ' ') {
            resultAux += ' ';
        } else {
            for (let i = 0; i < alpha.length; i++) {
                if(msg[j] === alpha[i]) {
                    let num = (i - step) % alpha.length
                    resultAux += alpha[num];
                }
            }
        }
    }
    resultChanged(resultAux);
}

render() {
    return (
        <div>
            <input onChange={this.props.msgChanged} type='text' value={this.props.message.msg} />
            <Button action={this.encrypt} label='Criptografar' />
            <Button action={this.decrypt} label='Descriptografar' />
            <Button action={this.props.clear} label='Apagar' />
            <p>{this.props.message.result}</p>
        </div>
    )
}

};

const mapStateToProps = state => ({ message: state.message, counter: state.counter });
const mapDispatchToProps = dispatch => bindActionCreators({ msgChanged,   resultChanged, clear }, dispatch);

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

Action:

export const resultChanged = function(resultMsg) {
  console.log('action', resultMsg);
  return {
    type: 'RESULT_CHANGED',
    payload: resultMsg
  }
}

Reduce:

const INITIAL_STATE = {
msg: '',
result: '',
alpha: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']

}

export default (state = INITIAL_STATE, action) => {
  console.log(action.type, action.payload);
  switch(action.type) {
    case 'MSG_CHANGED':
        return { ...state, msg: action.payload };
        break;
    case 'RESULT_CHANGED':
        console.log('reducer', action.payload)
        return { ...state, result: action.payload };
        break;
    case 'CLEAR':
        return { ...state, msg: '' };
        break;
    default:
        return state;
  }
}
  • Give a console.log({ ...state, result: action.payload }) inside the RESULT_CHANGED case to see if anything appears. If it appears, then it’s all right in the Reset and the problem is when you do the mapStateToProps.

  • If you only have a single Return (what you wrote), then the problem is why you use { message: state.message, counter: state.counter }, but in the return you arrow "msg" and not message. And in result changed, arrow Voce result, not included in mapStateToProps.

  • Thanks for the help, but unfortunately as I said it does not enter the Reset, I put the console.log just to remove the doubt but nothing happens. The console.log it has in the action is running but then stops there. As for the answer I am using two: ;import { combineReducers } from 'redux';&#xA;&#xA;import counterReducer from '../reducer/counterReducer';&#xA;import messageReducer from '../reducer/messageReducer';&#xA;&#xA;const rootReducer = combineReducers({&#xA; counter: counterReducer,&#xA; message: messageReducer&#xA;});&#xA;&#xA;export default rootReducer;

  • The other actions that use the same reset work correctly, only the one that receives a variable to run that does not work, this variable comes from a function within the...

1 answer

1

One of the possible problems is that you are not using Object.assign in your reducers:

export default (state = INITIAL_STATE, action) => {
  switch(action.type) {
    case 'MSG_CHANGED':
        return Object.assign({}, state, { msg: action.payload });
    case 'RESULT_CHANGED':
        return Object.assign({}, state, { result: action.payload });
    case 'CLEAR':
        return Object.assign({}, state, { msg: '' });
    default:
        return state;
  }
}

The way you are implementing may be changing your state.

To help you with problems like this I advise you to use the library

Redux-immutable-state-invariant

The word break is not required after the word Return;

It would be interesting to use a lint like Eslint or prettier that will help you encode better.

  • In fact, the problem was solved using a simple this.props.resultChanged(resultAux) within the component. As for the break it is important that it is used because there may be a bug that leaks the instruction, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch .

  • With respect to break, in the documentation you sent from Mozilla shows nothing with break after a Return. This Eslint link shows exactly what I’m talking about: http://eslint.org/docs/rules/no-unreachable

Browser other questions tagged

You are not signed in. Login or sign up in order to post.