0

I am working with React and Realtime Database.

Here are the 2 main database nodes related to this question:

enter image description here

and:

enter image description here

Below is the relevant code:

class App extends React.Component {
  constructor(props) {
    super(props);
    firebase.initializeApp(config);

    this.state = {
      commandes: []
    };
  }

  componentDidMount() {
    this.getData();
  }

  getData = () => {
    let ref = firebase.database().ref("/");
    ref.on("value", snapshot => {
      const state = snapshot.val();
      this.setState(state);
    });
  };

  .....

  render() {
    const { commandes } = this.state;
    return (
      <React.Fragment>
        .....
              {commandes.map(item => (
                <div
                  key={item.name}
                  className="card float-left"
                  style={{ width: "18rem", marginRight: "1rem" }}
                >
                </div>
              .....
              ))}
        .....
      </React.Fragment>
    );
  }
}

It does not work and this is the error I am getting:

TypeError: commandes.map is not a function

This is the reason of my posting this. And I'd be glad to get some feed back or tips as to solving this issue.

Now here is one important note: when using the same code as above, only changing the 3 occurences of commandes to developers, then the code works perfectly, listing the items in the collection developers as I expect. Though I have spent some time trying a few things to figure out the problem, it does not work. Since I am not changing the code (other than what I just mentioned) I assume the differencence is between the collections, but I can't really see what.

Here is the function creating one item in the commandes collection:

  sendCommande = item => {
    const orderTime = new Date(),
    orderKey = orderTime.getTime().toString(),
    orderOject = {
      name: item.name,
      price: item.price,
      dateTime: orderTime.toLocaleString(),
      status: 1,
      uid: orderKey
    }

    firebase.database()
    .ref("/commandes/"+orderKey)
    .set(orderOject);
  };
Michel
  • 10,303
  • 17
  • 82
  • 179
  • Can you share the code that populate the `commandes` array? – Renaud Tarnec Nov 03 '21 at 08:58
  • @Renaud_Tarnec. I just edited the post, adding what you want (before render()) and just in case adding some more useful code at the end. I hope it is going to be useful, let me know if you need more please. – Michel Nov 03 '21 at 09:16

1 Answers1

1

I assume the differencence is between the collections (i.e. the database nodes), but I can't really see what

The reason is that for the developers node the subnodes keys are in a sequence: 0, 1, 2. The val() method interprets that as an Array.

The subnodes keys of the commandes node are not following a sequence: therefore the val() method returns a JavaScript Object (which is not an Array), hence the error with map().


Notre that some subnode keys like 1,2,4,6 will also return an Array: the val() method detects a sequence (1,2) and returns an Array with some null elements at indexes 0, 3 and 5.

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
  • I see. That makes sense indeed. But how should I read them in this case? There must be a way to get the information in the commandes collection too. – Michel Nov 03 '21 at 09:23
  • "There must be a way to get the information in the commandes collection too" => Sure, you can generate an Array from the JavaScript object, for example with the [`values()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values) method. See also https://www.javascripttutorial.net/object/convert-an-object-to-an-array-in-javascript/ – Renaud Tarnec Nov 03 '21 at 09:25
  • 1
    Update to my above comment: For the `commandes` node the `val()` method will return a map of objects (map of maps), therefore the methods mentioned above will not help. You will need to loop over the object to extract the name value and build an Array. See https://stackoverflow.com/questions/14810506/map-function-for-objects-instead-of-arrays – Renaud Tarnec Nov 03 '21 at 09:29
  • I had a look at the accepted answer in the post you mention. For the time being, it does seem to work. – Michel Nov 03 '21 at 15:02
  • @Michel Glad I could help you. You may accept and upvote my answer if it answered your question "I assume the difference is between the collections, but I can't really see what". Thanks. – Renaud Tarnec Nov 03 '21 at 15:20
  • Yes, I had to dig into it for a while but now it works fine. That's actually why I did not accept the answer sooner. Thanks! – Michel Nov 04 '21 at 06:08