0

I have the below data set Json file.

Upon ajax retrieval of the json file, i called the following reducer.

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

    switch(action.type) {

        case GET_CLIENT_SUCCESS:
            return action.payload;

        default:
            return state;
    }

}

I would like to use reverse() and .map on this.state.client.notes however I'm keep getting undefined or null error. turn out when I do the following...

console.log(typeof this.state.client); //returns object
console.log(typeof this.state.client.notes); //returns undefined

I've make sure i return the json file in the correct format(hopefully) but i don't understand why the nested state is not an object but undefined. Anyway to fix this so I can use the .reverse() and .map function, or is this working as intended? If it's working intended is there an alternative other than creating a separate reducer. I want the notes to be under the client state.

    {
    "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."
        }
    }
}

Thank you for figuring out, and if i put console.log in render() i did get it returned as object. I'm a stuck because i also referre to this link

map function for objects (instead of arrays)

so I have the following codes insider render()

//$.map(this.props.client.notes, function(note, key) { //This works, but i cannot use reverse()

//Object.keys(this.props.client.notes).map(function(key, note) { //this doesn't work and return error


Object.keys(this.props.client.notes).map(function(key, index) {

 return (
    <li key={key}>

    <div>Key: {key} | Note_id: {this.props.client.notes[index].noteId} AND Note_content: {this.props.client.notes[index].note}</div>
    </li>

);

Now we figure out it's an object, but the code above still don't work. If i can figure out the data type of the client state, then i can know what to do.

in the mean time, the aboves return following error ×

TypeError: Cannot convert undefined or null to object

Updated: Codes with condition Following answers below I updated my codes, created a function of printNote() and put {this.printNote} inside render.

I can see the console log of all the keys, however, it's not being rendered on screen.

printNote() {
        console.log(this.props);
        console.log(this.props.client.notes);

        let notes = this.props.client.notes;
        console.log('notes',notes);
        if(notes) {
            console.log('in if ');
             Object.keys(notes).map(function(key, index) {


                    console.log(key);
                    return (
                            <li key={key}>
                                <div>Key: {key} | Note_id: {notes[index].noteId} AND Note_content: {notes[index].note}</div>
                            </li>


                    );

                })

            }
        }
Someone Special
  • 12,479
  • 7
  • 45
  • 76
  • first of all you can't use `.map` on `notes` as it isn't an `array` but an `object`. and where is the `clent` key coming from? i don't see it in your json file, is this the name of the `reducer`? – Sagiv b.g Nov 11 '17 at 10:38
  • yes it is the reducer. sorry I need your help again. It's the initial stage i need to get everything right. – Someone Special Nov 11 '17 at 10:42
  • 1
    show the code where you try to enter the `notes` with this line `console.log(typeof this.state.client.notes);` my bet is that you try accessing it before the fetch is done and you get the initial state (which is an empty object) – Sagiv b.g Nov 11 '17 at 10:43
  • oh u r right, i put it in Render() and it shows it as Object. Should i change the question? How to change the object into array. – Someone Special Nov 11 '17 at 10:55
  • your question is "__why client.notes returns undefined__". well you got an answer to this. as for how to change your data shape this could be a new question but i'm sure there is already an answer for this so all you need to do is search for it – Sagiv b.g Nov 11 '17 at 10:59
  • there is a reason why I'm asking this because of my updated codes above can u take a look? – Someone Special Nov 11 '17 at 11:12

1 Answers1

1

You did not post the code where you are trying to access the object:

this.state.client.notes

But my bet is that you are trying to access it before the fetch operation (whic is asynchronous) is finished, hence you get the initial state of the client reducer which is the empty object.

As for using .map on notes this won't work because .map belongs to the Array.prototype and notes is an object not an array.

Edit
As a followup to your update.

This a simple case where the render method runs before you get any data back from the server.
When you want to render data that is fetched async, you should do it conditionally.

For example:

const { client } = this.props; // just destructuring the object for shorter lines
client.notes && Object.keys(client.notes).map(function(key, index) {

      return ( < li key = {
            key
          } >

          < div > Key: {
            key
          } | Note_id: {
            this.props.client.notes[index].noteId
          }
          AND Note_content: {
            this.props.client.notes[index].note
          } < /div> < /li> 

The map line will only execute if client.notes will return a truthy value (these are the falsy values)

Sagiv b.g
  • 30,379
  • 9
  • 68
  • 99