Skip to content

VirtualizedList.RenderItem throws when using function component with hooks#24832

Closed
adkenyon wants to merge 13 commits into
facebook:masterfrom
adkenyon:render-item-function-component-with-hooks-bug
Closed

VirtualizedList.RenderItem throws when using function component with hooks#24832
adkenyon wants to merge 13 commits into
facebook:masterfrom
adkenyon:render-item-function-component-with-hooks-bug

Conversation

@adkenyon
Copy link
Copy Markdown
Contributor

@adkenyon adkenyon commented May 13, 2019

Summary

<VirtualizedList /> will throw an error if the renderItem Prop component uses hooks. Function components without hooks and class components work without issue.

Super contrived Example

function FlatListItem({ item }) {
  React.useEffect(() => console.log(item),[])

 return (<Text>{item}</Text>);
}

<FlatList data={[1, 2, 3]} renderItem={FlatListItem} />

Example Error:

Invariant Violation: Hooks can only be called inside the body of a function component. (https://fb.me/react-invalid-hook-call)

This error is located at:
    in CellRenderer (at VirtualizedList.js:688)
    in RCTScrollContentView (at ScrollView.js:976)
    in RCTScrollView (at ScrollView.js:1115)
    in ScrollView (at VirtualizedList.js:1081)
    in VirtualizedList (at FlatList.js:632)
    in FlatList (at WithoutScrollbars.js:21)
    ...

Changelog

[General] [Added] - VirtualizedList ListItemComponent. An alternative to renderItem that accepts function components with hooks.
[General][Added] - FlatList ListItemComponent. An alternative to renderItem that accepts function components with hooks.
[General][Added] - VirtualizedList and FlatList tests and updated RNTester example

Test Plan

Updated JS tests for VirtualizedList and tested on local build.

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label May 13, 2019
@adkenyon adkenyon changed the title Render item function component with hooks bug VirtualizedList.RenderItem throws when using function component with hooks May 13, 2019
Copy link
Copy Markdown
Contributor

@cpojer cpojer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Thank you for fixing this issue.

Copy link
Copy Markdown
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpojer is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@cpojer
Copy link
Copy Markdown
Contributor

cpojer commented May 14, 2019

I spent some time thinking about this and I'm worried about the performance implications of this breaking change because of the added wrapping for each cell. I think renderItem is also a misleading prop name.

How about this:

  • Add a new prop called item which takes a React component
  • If item is specified, use it with React.createElement
  • If item isn't specified, fall back to renderItem (this ensures the default behavior stays the same)
  • If both item and renderItem are specified, we should console.warn and explain that one takes precedence over the other.

Then in the future we can remove renderItem completely.

Copy link
Copy Markdown

@analysis-bot analysis-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code analysis results:

  • flow found some issues.

Comment thread Libraries/Lists/FlatList.js Outdated
Comment thread Libraries/Lists/FlatList.js Outdated
Comment thread Libraries/Lists/FlatList.js Outdated
Copy link
Copy Markdown

@analysis-bot analysis-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code analysis results:

  • eslint found some issues. Run yarn lint --fix to automatically fix problems.

Comment thread Libraries/Lists/FlatList.js Outdated
Comment thread Libraries/Lists/FlatList.js Outdated
@adkenyon
Copy link
Copy Markdown
Contributor Author

adkenyon commented May 14, 2019

@cpojer Implemented your suggestions.

  • I Used ListItemComponent rather than Item. I think it follows the existing naming convention.
  • Minor flow type cleanup
  • After adding console.warn for the condition that both ListItemComponent and renderItem are present I noticed that FlatList would constantly throw warnings as FlatList always returns an implementation of renderItem (to handle multiple columns). I was able to fix this for FlatList, but VirtualizedSectionList and SectionList have the same issue. I'm thinking that I'll follow up with the ListItemComponent implementation for VirtualizedSectionList and SectionList on another PR.

@react-native-bot react-native-bot added the Type: Enhancement A new feature or enhancement of an existing feature. label May 14, 2019
Copy link
Copy Markdown
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpojer has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

Comment thread Libraries/Lists/FlatList.js Outdated
Copy link
Copy Markdown
Contributor

@sahrens sahrens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, much cleaner :)

@cpojer
Copy link
Copy Markdown
Contributor

cpojer commented May 17, 2019

I applied the change internally and I'm trying to land it :) Thanks for going through all the iterations with us @adkenyon!

@react-native-bot
Copy link
Copy Markdown
Collaborator

This pull request was successfully merged by @adkenyon in 57a1e7c.

When will my fix make it into a release? | Upcoming Releases

@react-native-bot react-native-bot added the Merged This PR has been merged. label May 20, 2019
vovkasm pushed a commit to vovkasm/react-native that referenced this pull request Aug 12, 2019
…hooks (facebook#24832)

Summary:
`<VirtualizedList />` will throw an error if the `renderItem` Prop component uses hooks. Function components without hooks and class components work without issue.

Super contrived Example
```{js}
function FlatListItem({ item }) {
  React.useEffect(() => console.log(item),[])

 return (<Text>{item}</Text>);
}

<FlatList data={[1, 2, 3]} renderItem={FlatListItem} />
```

Example Error:
```
Invariant Violation: Hooks can only be called inside the body of a function component. (https://fb.me/react-invalid-hook-call)

This error is located at:
    in CellRenderer (at VirtualizedList.js:688)
    in RCTScrollContentView (at ScrollView.js:976)
    in RCTScrollView (at ScrollView.js:1115)
    in ScrollView (at VirtualizedList.js:1081)
    in VirtualizedList (at FlatList.js:632)
    in FlatList (at WithoutScrollbars.js:21)
    ...
```

## Changelog

[General] [Added] - VirtualizedList ListItemComponent. An alternative to renderItem that accepts function components with hooks.
[General][Added] - FlatList ListItemComponent. An alternative to renderItem that accepts function components with hooks.
[General][Added] - VirtualizedList and FlatList tests and updated RNTester example
Pull Request resolved: facebook#24832

Reviewed By: sahrens

Differential Revision: D15334020

Pulled By: cpojer

fbshipit-source-id: 882db722fd6e22f07260b08091b3456d1c66c2c8
(cherry picked from commit 57a1e7c)
M-i-k-e-l pushed a commit to M-i-k-e-l/react-native that referenced this pull request Mar 10, 2020
…hooks (facebook#24832)

Summary:
`<VirtualizedList />` will throw an error if the `renderItem` Prop component uses hooks. Function components without hooks and class components work without issue.

Super contrived Example
```{js}
function FlatListItem({ item }) {
  React.useEffect(() => console.log(item),[])

 return (<Text>{item}</Text>);
}

<FlatList data={[1, 2, 3]} renderItem={FlatListItem} />
```

Example Error:
```
Invariant Violation: Hooks can only be called inside the body of a function component. (https://fb.me/react-invalid-hook-call)

This error is located at:
    in CellRenderer (at VirtualizedList.js:688)
    in RCTScrollContentView (at ScrollView.js:976)
    in RCTScrollView (at ScrollView.js:1115)
    in ScrollView (at VirtualizedList.js:1081)
    in VirtualizedList (at FlatList.js:632)
    in FlatList (at WithoutScrollbars.js:21)
    ...
```

## Changelog

[General] [Added] - VirtualizedList ListItemComponent. An alternative to renderItem that accepts function components with hooks.
[General][Added] - FlatList ListItemComponent. An alternative to renderItem that accepts function components with hooks.
[General][Added] - VirtualizedList and FlatList tests and updated RNTester example
Pull Request resolved: facebook#24832

Reviewed By: sahrens

Differential Revision: D15334020

Pulled By: cpojer

fbshipit-source-id: 882db722fd6e22f07260b08091b3456d1c66c2c8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Component: VirtualizedList Merged This PR has been merged. Type: Enhancement A new feature or enhancement of an existing feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants