React and Redux: Extract Local State into Redux

Hello,

I am having one question regarding this challenge.

The original code before changes:

// React:
const Provider = ReactRedux.Provider;
const connect = ReactRedux.connect;

// Change code below this line
class Presentational extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: '',
      messages: []
    }
    this.handleChange = this.handleChange.bind(this);
    this.submitMessage = this.submitMessage.bind(this);
  }
  handleChange(event) {
    this.setState({
      input: event.target.value
    });
  }
  submitMessage() {
    this.setState((state) => ({
      input: '',
      messages: state.messages.concat(state.input)
    }));
  }

The codes after changes:

// React:
const Provider = ReactRedux.Provider;
const connect = ReactRedux.connect;

// Change code below this line
class Presentational extends React.Component {
  constructor(props) {
    super(props);
    
    // Remove property 'messages' from Presentational's local state
    this.state = {
      input: ''
    }
    this.handleChange = this.handleChange.bind(this);
    this.submitMessage = this.submitMessage.bind(this);
  }
  handleChange(event) {
    this.setState({
      input: event.target.value
    });
  }
  submitMessage() {
  
    // Call 'submitNewMessage', which has been mapped to Presentational's props, with a new message;
    // meanwhile, remove the 'messages' property from the object returned by this.setState().
    this.props.submitNewMessage(this.state.input);
    this.setState({
      input: ''
    });
  }

In the original code, there is this line doing concatenation for input and messages:

messages: state.messages.concat(state.input)

But where is this action being done after changes?

Any ideas?

Thank you.

Hi @yuchit. I think your clue is in the code below.

const mapDispatchToProps = (dispatch) => {
  return {
    submitNewMessage: (message) => {
      dispatch(addMessage(message))
    }
  }
};

submitNewMessage is now a prop inside your component and it is a function. Its declaration is the return value of mapDispatchToProps.

const submitNewMessage = (message) => {
    dispatch(addMessage(message));
}

When you call submitNewMessage via props like props.submitNewMessage(message), you pass the message as argument and inside it will dispatch an action for you. So the details of action dispatch has been hidden from you. What you simply need to do is invoke it with the message as argument and your state will be updated in the redux store.
You can read more about mapStateToProps and mapDispatchToProps at the react-redux site.

1 Like

Hi @nibble
Thank you very much for the reply.
I was looking for where the concatenation is being defined…
I reviewed all the flow again and I think reducer is probably the place where concatenation is being defined:

    case ADD:
      return [
        ...state,
        action.message
      ];

Otherwise, I couldn’t find anywhere exactly for this move.

Yes, I think you are right that it starts from mapDispatchToProps, and then it returns a function where message invokes addMessage(message) to be dispatched.
addMessage(message) updates message and then the reducer concatenates message to previous message.
Hopefully my this understanding is correct.

You are right that is where the concatenation is taking place. In Redux, you are not supposed to mutate state but return new state all the time. That is why spread syntax is preferred. The spread syntax i.e. [...state] is used to copy all the elements of state to a new array and appending the new message at the end. Below is what is happening in the reducer.

  const state  = ["message 1", "message 2", "message 3"];
  const action = {type: "ADD", message: "message 4"};
  const new State = [...state, action.message]; // This is what is returned

If you still want to use concat then you can do something like:

case ADD:
    return state.concat(action.message);

For more on how to use spread syntax with array literals, you can check out MDN.

1 Like

@nibble, thank you very much for the reply and makes this more clear :pray: