omniscientjs / immstruct

Immutable data structures with history for top-to-bottom properties in component based libraries like React. Based on Immutable.js
374 stars 21 forks source link

Playing with Ramda. Warning on length #87

Closed wcastand closed 7 years ago

wcastand commented 8 years ago

Hi, I'm a fresh user of React, immstruct so forgive me if i'm doing it badly. :)

This is my store so far:

   let initialState = {
     entries: [],
     monthly: [],
     inputs: {
       title: '',
       price: '',
       created_at: moment().format('YYYY-MM-DD'),
     }
   }

So i have a store (immstruct) and i use immstruct-actions to play with it. when i add an entry, i use a function created with ramda to get my id:

const isMax = (x, y) => y.id > x ? y.id : x
const getId = R.compose(R.add(1), R.reduce(isMax, 0))

and i use it like this :

  let entries = store.cursor().get('entries')
  let new_id = getId(entries)

The problem is when i'm doing this for the first time (my array entries is empty), i don't get and array but an IndexedCursor and the console tell me this warning:

//value of my entries
IndexedCursor {size: 0, _rootData: Object, _keyPath: Array[1]}

//warning message
'iterable.length has been deprecated, use iterable.size or iterable.count(). This warning will become a silent error in a future version. Error'

But once i get an item in my entries, i get an array from store.cursor().get('entries') so the warning doesn't appear anymore.

Ramda uses the length property of the array and i can't modify this since it's in the source code. So in your next version my code will throw an error and i don't how to avoid that.

mikaelbr commented 8 years ago

Usually, when you get the error iterable.length has been deprecated it's due to trying to use an immutable data structure as a "native object". For instance, when passing an immutable list to a reduce function of another library which expects normal objects.

In your case this is where it happens:

const isMax = (x, y) => y.id > x ? y.id : x
const getId = R.compose(R.add(1), R.reduce(isMax, 0))

Inside Ramdas reduce it checks the length of the object it is passed (which is not valid check for immutable types). If you rather convert the immutable object to a native object before passing it into your functions, it'll work as expected:

let entries = store.cursor().get('entries')
let new_id = getId(entries.toJS())

Notice, now you no longer have an immutable object, but a regular mutable object, but in your case it works just fine, as you are only trying to get the ID.

Hope this helps.

wcastand commented 8 years ago

It helps but an other problem appears x)

When i'm not using toJS(), i get a warning when my entries are empty because store.cursor().get('entries') sends me an IndexedCursor but once i put an entry in it, store.cursor().get('entries') sends me and array and i don't get the warning anymore.

When i use toJS(), i don't get the warning anymore when my entries are empty. But i get an error when my entries have one or more entry because store.cursor().get('entries') send an array and an Array doesn't have the function toJS()