recyclerlistview icon indicating copy to clipboard operation
recyclerlistview copied to clipboard

Any example using hooks?

Open SunskyXH opened this issue 4 years ago • 8 comments

Hi guys! I'm working on RLV with react hooks, and here comes an issue that when using forceNonDeterministicRendering. I've given estimated height to LayoutProvider, and it works well in the first rendering, but then I refresh the list by pulling down <RefreshControl /> component, the item height becomes the estimated height rather than the real height. Then I find out that it is because I've used dataProvider in the layoutProvider. The codes are something like:

  // I'm using useState hooks because dataProvider are saved in the component's state in the example code
  const [dataProvider, setDataProvider] = useState<DataProvider>(
    new DataProvider((r1, r2) => r1 !== r2),
  )

  const layoutProvider = useMemo(
    () =>
      new LayoutProvider(
        index => {
          const item = dataProvider.getDataForIndex(index)
          return item.type
        },
	    (type, dim) => {
	      //...
        },
      ),
    [dataProvider],
  )

  // this is how I update dataProvider
  useEffect(() => {
	setDataProvider(d => d.cloneWithRows(listData))
  }, [listData])

I think this problem may be caused by updating layoutProvider or dataProvider incorrectly. And I tried to find best practice when using react hooks but I didn't make it. Could you please offer some demo using react hooks? I'll appreciate your help very much!

SunskyXH avatar Jun 01 '20 03:06 SunskyXH

Hello there! Right now I'm facing a similar issue, better described here https://stackoverflow.com/questions/59573435/recyclerlistview-scrolls-to-top-onendreached-with-functional-component and in #449.

My code is quite like @SunskyXH 's, but instead of using the useMemo hook, I'm using layoutProvider as a state to prevent recreating it. Everything works pretty well, until I try to access the dataProvider state inside layoutProvider, which is done because my item layout depends on the data content (apparently using layoutProvider as a state with useState hook doesn't get the updated value of dataProvider's state, any idea on that?).

Until now I wasn't able to figure what the problem is, but looking foward to try the workaround presented by Mike in the StackOverflow question. I'd also appreciate a demo using react hooks. Thanks in advance!

EmersonPinheiro avatar Jun 20 '20 21:06 EmersonPinheiro

+1

abduraufsherkulov avatar Jul 12 '20 15:07 abduraufsherkulov

@EmersonPinheiro this is for same height items. is there the way to implement variety height items depend on item info?

dzpt avatar May 09 '21 10:05 dzpt

@dzpt, yes, you can use the forceNonDeterministicRendering prop (docs) But, I think it may affect list's performance a bit if you don't provide close estimated measures.

In my case, to workaround the original issue, I ended up using Class Components instead Functional ones. That said, I do have implemented a list with variable height items. It was a text list, which may contain texts of different lengths. So, in order to achieve that I used the react-native-text-size and stored each item's height in an array. So I used this array in layoutProvider to associate each measure to it's corresponding item.

EmersonPinheiro avatar May 14 '21 21:05 EmersonPinheiro

@dzpt @EmersonPinheiro @abduraufsherkulov did you find any workaround?

prayaslashkari avatar Jan 12 '22 17:01 prayaslashkari

Hey @callmemonky, I ended up using Class Components. I didn't try any new solution since.

EmersonPinheiro avatar Jan 12 '22 19:01 EmersonPinheiro

Hey @callmemonky, I ended up using Class Components. I didn't try any new solution since.

Solution that worked for me.

const _dataProvider = useMemo(() => {
  return new DataProvider((r1, r2) => {
    return r1 !== r2;
  });
}, []);

const newDataProvider = useMemo(() => {
  return _dataProvider.cloneWithRows(listData);
}, [listData]);


const _layoutProvider = useMemo(() => {
  return new LayoutProvider(
    (index) => {
      console.log(newDataProvider.getDataForIndex(index)); //This will work.
      return 1;
    },
    (type, dim) => {
      switch (type) {
        case 1:
          dim.width = width;
          dim.height = 100;
          break;
        default:
          dim.width = 0;
          dim.height = 0;
      }
    }
  );
}, [newDataProvider]);

prayaslashkari avatar Jan 12 '22 19:01 prayaslashkari

Cool! Unfortunately, I don't work on the project where I used this lib anymore, so I won't be able to test this solution, but good to know it worked for you.

EmersonPinheiro avatar Jan 12 '22 21:01 EmersonPinheiro