cooperka / react-native-immutable-list-view

:scroll: Drop-in replacement for ListView, FlatList, and VirtualizedList.
MIT License
205 stars 30 forks source link

Row will not be refreshed #17

Closed lucaslz2020 closed 7 years ago

lucaslz2020 commented 7 years ago

RowHasChanged whether this function can be made public。 becase when I change object , but row will not be refreshed. I think Immutable.is can not meet my requirements

cooperka commented 7 years ago

Hi @lucasleelz, could you please provide some example code so I can see what's going on? Immutable.is should always return false if any part of your data has changed, assuming it's fully Immutable and doesn't contain any plain objects or arrays inside of it.

You also need to make sure that your list can be rendered with ONLY the data contained in the list itself. If you're computing things using props or state in your renderItem, it will get out of sync quickly.

If you post a link to your project or at least some example code here I can try to help you more.

lucaslz2020 commented 7 years ago

I am very happy to receive your reply,It 's too late now, and tomorrow morning I'll give you an example。 thanks.

On 03/21/2017 22:35, Kevin Cooper wrote: Hi @lucasleelz, could you please provide some example code so I can see what's going on? Immutable.is should always return false if any part of your data has changed, assuming it's fully Immutable and doesn't contain any plain objects or arrays inside of it. You also need to make sure that your list can be rendered with ONLY the data contained in the list itself. If you're computing things using props or state in your renderItem, it will get out of sync quickly. If you post a link to your project or at least some example code here I can try to help you more.

—You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub, or mute the thread.

{"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/cooperka/react-native-immutable-list-view","title":"cooperka/react-native-immutable-list-view","subtitle":"GitHub repository","main_image_url":"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Open in GitHub","url":"https://github.com/cooperka/react-native-immutable-list-view"}},"updates":{"snippets":[{"icon":"PERSON","message":"@cooperka in #17: Hi @lucasleelz, could you please provide some example code so I can see what's going on? Immutable.is should always return false if any part of your data has changed, assuming it's fully Immutable and doesn't contain any plain objects or arrays inside of it.\r\n\r\nYou also need to make sure that your list can be rendered with ONLY the data contained in the list itself. If you're computing things using props or state in your renderItem, it will get out of sync quickly.\r\n\r\nIf you post a link to your project or at least some example code here I can try to help you more."}],"action":{"name":"View Issue","url":"https://github.com/cooperka/react-native-immutable-list-view/issues/17#issuecomment-288097571"}}}

lucaslz2020 commented 7 years ago

@cooperka Hi, I wrote an example. https://github.com/lucasleelz/ImmutableListViewExample.git. I copied ImmutableListView.js and utils.js file in my environment and modified therowHasChanged method, this will refresh row description. if replaced react-native-immutable-list-view, it doestn't work.

cooperka commented 7 years ago

Thanks for the demo project! It looks like you're using a plain JS class (Row) as part of your list data. You could either turn that into Immutable.Map, or implement custom methods called equals() and hashCode() on the class. See https://facebook.github.io/immutable-js/docs/#/is for more details.

This is because Immutable has no way of knowing whether one class is the same as another class unless you define a method it can use to test equality.

Here's an example of a method you can use instead of your class Row { ... }; it should work exactly the same:

function getRowItem(name, description, level = 1, isOpen = false) {
  return Immutable.Map({ name, description, level, isOpen });
}

Then use getRowItem('ROW A', 'test data') instead of new Row('ROW A', 'test data').

Please try it out and let me know if it works. I'm happy to help more if you're still having issues.

lucaslz2020 commented 7 years ago

Thank you for your careful answer, the use of Map can be refreshed. But it is not good enough, because every time I need get method to get the attribute value (map.get ('key') instead of map.key).

implement custom methods called equals() and hashCode() on the class, I don't know how to do it.

I want to implement a three-level tree function, click on a level or two can be expanded or folded. Do you have some good suggestions?

I think Section can use an object, I see what you are doing is using a string. Is there a way to do it? look like the following code

const data = Immutable.fromJS([
    {'name': 'section A ', 'description': 'a', 'children': ['foo', 'bar']},
    {'name': 'section B ', 'description': 'b', 'children': ['foo', 'bar']},
    {'name': 'section C ', 'description': 'c', 'children': ['foo', 'bar']},
]);
cooperka commented 7 years ago

@lucasleelz the reason you need to use .get('key') instead of just .key is to preserve immutability. If anyone had access to the raw data, they could mutate it, which would defeat the purpose. Here's a trick if you don't like typing the extra characters -- you can use object destructuring to do it for you:

const { key } = map;
console.log(key);

As for your question above, I'd structure your data like this:

{
  'Section A': {
    description: 'something',
    children: ['foo', 'bar'],
    isExpanded: false,
  },
  'Section B': {
    ...
  },
}

Then in your renderSectionHeader(sectionData, category) method, you'll receive 'Section A' for the category, and in your renderRow(rowData) you can use const { description, children, isExpanded } = rowData; to get all your variables.

Does that make sense?

lucaslz2020 commented 7 years ago

Thank you very much~

const { key } = map;
console.log(key);

If Map of immutable is not working。 But I can use the toJSON, toObject, toJS method to solve this problem

cooperka commented 7 years ago

@lucasleelz you shouldn't ever need to use those methods to access the data. They're slow and inefficient, and they make it pointless to use Immutable data if you're just going to make it mutable every time you use it 😛

You're right though, I forgot that I'm using a babel plugin to get destructuring to work for Immutable data. You'll need to install extensible-destructuring and then it should work as described earlier. Sorry for the confusion.

lucaslz2020 commented 7 years ago

@cooperka thanks for your reminder.

lucaslz2020 commented 7 years ago

@cooperka Hi, For your answer

{
  'Section A': {
    description: 'something',
    children: ['foo', 'bar'],
    isExpanded: false,
  },
  'Section B': {
    ...
  },
}

I need children to render to row, but now it will render description: 'something', children: ['foo', 'bar'], isExpanded: false, to row. I need foobar of children to render row view.

display effect

sectionA isExpanded  description
   foo
   bar
sectionB isExpanded  description
   row1
   row2
cooperka commented 7 years ago

Can you just render multiple elements in renderRow? e.g.

renderRow(rowData) {
  const { children } = rowData;
  const childItems = children.map((child, index) => <Text key={index}>{child}</Text>);
  return (
    <View>
      {childItems}
    </View>
  );
}
lucaslz2020 commented 7 years ago

When the amount of data is large when it will affect the performance of it? I hope that every child in children will renderRow.

renderRow(rowData) {
   const {child} = rowData;
   ...
}
cooperka commented 7 years ago

It should be perfectly fine for performance :) No reason to overcomplicate things.

cooperka commented 7 years ago

You can always just try it out and if performance is a problem, then you can try to optimize.

lucaslz2020 commented 7 years ago

OK.

lucaslz2020 commented 7 years ago

@cooperka

{
  'Section A': {
    description: 'something',
    children: ['foo', 'bar'],
    isExpanded: false,
  },
  'Section B': {
    ...
  },
}

For this structure, renderRow , Each element in the Map is rendered once. So that in the section to add some additional data is not feasible

cooperka commented 7 years ago

You need to manually render each of the children, see code here: https://github.com/cooperka/react-native-immutable-list-view/issues/17#issuecomment-293896933. Does that make sense?

lucaslz2020 commented 7 years ago

That was not what I meant. Every key in the Map executes renderRow

renderRow(rowData) // rowData = description
renderRow(rowData) // rowData = children
renderRow(rowData) // rowData = isExpanded
cooperka commented 7 years ago

Oh, I see what you mean now. Have a look at How to Format Your Data; you could try putting the object into an array so that it treats the entire object as the row data. Example:

{
  'Section A': [{
    description: 'something',
    children: ['foo', 'bar'],
    isExpanded: false,
  }],
  'Section B': [{
    ...
  }],
}
lucaslz2020 commented 7 years ago

Thanks.