1

I've saved the following json file in the client state in the reducer. Now as I add new Notes, via ajax, I'm calling the NEW_NOTE_SUCCESS reducer, which is suppose to add the new note to existing note array.

export default function clientProfile(state={}, action) {

    switch(action.type) {


        case NEW_NOTE_SUCCESS:
            console.log(action.payload);
            return { ...state, notes: [...state.notes, action.payload] }

        default:
            return state;
    }

}

However, after I did the above, this.props.client.notes will only have the new note I added, but not the old ones.

What should i do to "push" the new note into the array, so I do not need to resend the notes json file everytime I add a new note.

PS: action.payload contains the following json.

{
            "noteId": "10000000",
            "customerId": "34",
            "createdBy": "1",
            "created": "1510316194",
            "note": "ADDED A NEW NOTE. NEED TO ADD TO STATE"
        }

this is the original json file on the intial load.

{
    "customerId": "34",
    "agentId": "1",
    "createdDate": "1510223892",
    "firstname": "John",
    "lastname": "Doe",
    "mobile": "123456789",
    "address": "Something email here",
    "notes": {
        "0": {
            "noteId": "1",
            "customerId": "34",
            "createdBy": "1",
            "created": "1510316194",
            "note": "add something"
        },
        "1": {
            "noteId": "2",
            "customerId": "34",
            "createdBy": "1",
            "created": "1510316527",
            "note": "add something"
        },
        "2": {
            "noteId": "3",
            "customerId": "34",
            "createdBy": "1",
            "created": "1510317177",
            "note": "add new thing"
        },
        "3": {
            "noteId": "4",
            "customerId": "34",
            "createdBy": "1",
            "created": "1510318448",
            "note": "something"
        },
        "4": {
            "noteId": "5",
            "customerId": "34",
            "createdBy": "1",
            "created": "1510318476",
            "note": "this would be note number 5, lets see whether we can get something from this."
        }
    }
}

Updated: Reducer Codes - Object instead of array.

case NEW_NOTE_COMPLETE:
    return { ...state, notes: {...state.notes, action.payload.noteId: action.payload} }
Someone Special
  • 12,479
  • 7
  • 45
  • 76
  • what should happen when you get a note with a key of `3` and you already got a note with that key? do you need to override it or change the key of the new note? – Sagiv b.g Nov 11 '17 at 09:02
  • only the noteId is unique so i am just pushing in to array key 5 for example – Someone Special Nov 11 '17 at 09:03
  • hmm seems to me that you got mixed data structure. you see, in your json file `notes` is an object but in your reducer it is an array. i would expect to see this line `notes: {...state.notes, "someKey": action.payload}` instead of this `notes: [...state.notes, action.payload]` – Sagiv b.g Nov 11 '17 at 09:05
  • Thanks @Sag1v. So I've changed on my server side to make the array key the noteId. So when I push the new note, the "someKey" will be my payload.noteId. However it's returning unexpected token error. – Someone Special Nov 11 '17 at 09:14
  • action.payload.noteId <- unexpected token refers to the . after action – Someone Special Nov 11 '17 at 09:14
  • you don't need to change the `json` structure, see my answer for more details – Sagiv b.g Nov 11 '17 at 09:23

1 Answers1

2

It seems to me that your data structure got mixed.
In your json file the note key is an object but inside your reducer you are handling it as an array.
So this line:

return { ...state, notes: [...state.notes, action.payload] }

Should be more like this (i just hard-coded the key 5 you should make it dynamic calculated somehow):

return {...state, notes: {...state.notes, "5": action.payload}}

Edit
As a followup to your comment:

but how do u make it dynamically calculated, it doesn't seems to let me use a variable

lets say you want to use noteId as your key, then you can use the computed property names of es2015

[action.payload.noteId]: action.payload

I updated the snippet to illustrate.

Here is small running example:

const jsonObj = {
  "customerId": "34",
  "agentId": "1",
  "createdDate": "1510223892",
  "firstname": "John",
  "lastname": "Doe",
  "mobile": "123456789",
  "address": "Something email here",
  "notes": {
    "0": {
      "noteId": "1",
      "customerId": "34",
      "createdBy": "1",
      "created": "1510316194",
      "note": "add something"
    },
    "1": {
      "noteId": "2",
      "customerId": "34",
      "createdBy": "1",
      "created": "1510316527",
      "note": "add something"
    },
    "2": {
      "noteId": "3",
      "customerId": "34",
      "createdBy": "1",
      "created": "1510317177",
      "note": "add new thing"
    },
    "3": {
      "noteId": "4",
      "customerId": "34",
      "createdBy": "1",
      "created": "1510318448",
      "note": "something"
    },
    "4": {
      "noteId": "5",
      "customerId": "34",
      "createdBy": "1",
      "created": "1510318476",
      "note": "this would be note number 5, lets see whether we can get something from this."
    }
  }
}

const newNote = {
  "noteId": "10000000",
  "customerId": "34",
  "createdBy": "1",
  "created": "1510316194",
  "note": "ADDED A NEW NOTE. NEED TO ADD TO STATE"
}
const action = {
  type: 'NEW_NOTE_SUCCESS',
  payload: newNote
};

function clientProfile(state = {}, action) {
  switch (action.type) {
    case 'NEW_NOTE_SUCCESS':
      {
        return {...state, notes: {...state.notes, [action.payload.noteId]: action.payload
          }
        }
      }

    default:
      return state;
  }
}


let reducer = clientProfile(jsonObj, {type: ''});
console.log("before the change",reducer.notes)
reducer = clientProfile(jsonObj, action);
console.log("after the change",reducer.notes)
Sagiv b.g
  • 30,379
  • 9
  • 68
  • 99
  • Thank u so much but how do u make it dynamically calculated, it doesn't seems to let me use a variable. I want to use action.payload.noteId as key, and I even tried {action.paload.noteId} and ${action.payload.noteId} – Someone Special Nov 11 '17 at 09:24
  • Its much better if you fixed the data structure issue to avoid any future patches like you going to do it now. for more you can read here from redux author https://stackoverflow.com/questions/33940015/how-to-choose-the-redux-state-shape-for-an-app-with-list-detail-views-and-pagina – RIYAJ KHAN Nov 11 '17 at 09:30
  • @SomeoneSpecial use computed property keys (I've updated my answer) – Sagiv b.g Nov 11 '17 at 09:32
  • 1
    I am looking at your data structure link. And i've tested your codes and it works! thank you for teaching me something new today! – Someone Special Nov 11 '17 at 09:35