tylermcginnis/re-base

syncState with nested objects giving me a run for my money.

ericwallen opened this issue · 5 comments

My issue is when I try to syncState with a nested object I get these errors:
Objects are not valid as a React child (found: object with keys {name, url, key}). If you meant to render a collection of children, use an array instead.

When I do this with a object with one level it works fine
componentDidMount(){ databaseBase.syncState('videos', { context: this, state: 'items', asArray: true }); }

When I do this with a object that holds other objects I get the error
componentDidMount(){ databaseBase.syncState('videos', { context: this, state: 'items', asArray: false }); }

I tried some variations of the settings but still can't figure it out. If you could help me I would be so grateful!

Thank you in advance.

Great package btw. I love it!

@ericwallen can you post your render method? If you are using asArray: true you'll get back an array of the first level of objects with data nested in those objects. If you use asArray:false its just one object so you would need to "unpack" it yourself. Here are some examples of how the render method would need to be different depending on which you are using. I am guessing you probably want asArray:true if videos is a collection of videos. asArray:false would be better to sync a single video object.

asArray:true

componentDidMount(){ 
  databaseBase.syncState('videos', { 
    context: this, 
    state: 'items', 
    asArray: true 
  }); 
  /* items will be an array that looks like 
    [{name: 'something', url: 'link', key: '-FirebaseGeneratedKey'}]
  */
}
render() {
  return (
    <div>
      {this.state.items.map(item => {
          return (
             <a href={item.url} key={item.key}>{item.name}</a>
           );
       })}
    </div>
  );
}

asArray:false

componentDidMount(){ 
  databaseBase.syncState('videos', { 
    context: this, 
    state: 'items', 
    asArray: false
  }); 
  /* items will be an object that looks like 
    {
      '-FirebaseKey1' : {
         name: 'Video 1',
         url: 'link...'
      },
      '-FirebaseKey2' : {
         name: 'Video 2',
         url: 'link...',
        ...etc
      },
    }
  */
}
render() {
  const { items } = this.state;
  return (
    <div>
      {Object.keys(items).map(key => {
          return (
             <a href={items[key].url} key={key}>{items[key].name}</a>
           );
       })}
    </div>
  );
}

Chris, you are the man. I seriously can not thank you enough. The second example you provided worked like a charm. Your package makes CRUD and managing State a complete breeze. This is literally the best stack ever! You are so awesome!

@ericwallen thanks! glad it worked. hoping you caught my typo in the second example. I had asArray: true by accident even though it was supposed to be the example for asArray: false

Ahh..ok Thanks for telling me! It synced with my state so I assumed my .map was the reason I couldn't iterate through.

So, this might be something you already wrote in your docs but wanted to leave a little update in case someone reads this thread later. I also needed to set the state of "items" to an empty array. If you don't do this and you try to pass that state to a different component it will show undefined if you log it to the console. It's tricky (at least to me) because my syntax was correct and "items" was in state. An array of objects that see that from the react developer tools.

Thanks again. Love this package!