Brandon Benefield
Brandon Benefield

Reputation: 1672

Understanding Redux and State

I've taken two courses, treehouse and one on udemy, on react/redux and just when I think to myself "hey you got this, let's do a little practice" I run into some huge bug I can't seem to diagnose.

What I'm trying to do here sounds very simple, and in plain javascript it works. My state is an empty object state = {} and when my action is called, it creates an array inside of state noteName. So at the end of the day state should look like state = { noteName: [ ...state.noteName, action.payload]}.

When I console.log(this.props.inputvalue) it will return whatever is in the input element. I thought I understood objects because that consolelog should return the array noteName and not the actual value, correct?

Code

actions/index.js

export const INPUT_VALUE = 'INPUT_VALUE';

export function addNoteAction(text) {
  return {
    type: INPUT_VALUE,
    payload: text
  }
}

reducers/reducer_inputvalue.js

import { INPUT_VALUE } from '../actions';

// state is initialized as an empty object here
export default function(state = {}, action) {
  switch (action.type) {
    case INPUT_VALUE:
      state.noteName = [];
      // this SHOULD create an array that concats action.payload with
      // whatever is already inside of state.name
      return state.noteName = [...state.noteName, action.payload];
    default:
      return state;
  }
}

noteitems.js

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

class NoteItems extends Component {
  render() {
    return (
      <ul>
        { 
          this.props.inputvalue.noteName 
          ?
          this.props.inputvalue.noteName.map((note, index) => {
            // this should iterate through noteName but returns undefined
            return <li key={index}>{note}</li>;
          }) 
          :
          <li>Nothing here</li>
        }
      </ul>
    );
  }
}

function mapStateToProps(state) {
  return {
    inputvalue: state.inputvalue
  }
}

export default connect(mapStateToProps)(NoteItems);

Upvotes: 1

Views: 66

Answers (2)

Julio Betta
Julio Betta

Reputation: 2295

This is happening because every time the action INPUT_VALUE is dispatched, you are resetting noteName. The main principle of redux is to not modify the state, but creating a new one based on the current. In your case:

const initialState = {
  noteName: []
};

export default function(state = initialState, action) {
  switch (action.type) {
    case INPUT_VALUE: return { 
      noteName: [...state.noteName, action.payload] 
    };

    default: return state;
  }
}

Upvotes: 1

LetterEh
LetterEh

Reputation: 26696

You are overwriting state.noteName in the first line of your switch case.

switch (action.type) {
  case INPUT_VALUE:
    state.noteName = [];

In Redux, the point is to never overwrite a value, but to return a new value that might be a brand-new value, might be a value that is based on the old value (but still a new value... not overwriting the old), or it might be returning the old value (completely unmodified).

const counterReducer = (counter, action) => {
  const options = {
    [COUNTER_INCREMENT]: (counter, action) =>
      ({ value: counter.value + 1 }),
    [COUNTER_DECREMENT]: (counter, action) =>
      ({ value: counter.value - 1 }),
    [COUNTER_RESET]: (counter, action) =>
      ({ value: 0 })
  };
  const strategy = options[action.type];

  return strategy ? strategy(counter, action) : counter;
};

At no point in that example am I modifying a value on counter. Everything is treated as read-only.

Upvotes: 0

Related Questions