react-native
react-native copied to clipboard
zIndex in a List
- [x] I have reviewed the documentation
- [x] I have searched existing issues
- [x] I am using the latest React Native version
This is actually a reopen of my #16878 issue. I've got some thumbs up, so I think I am not the only one with this issue. This time I updated my example project to a pure rn project with the latest release (rn Branche)
Environment
info
React Native Environment Info:
System:
OS: macOS High Sierra 10.13.6
CPU: (8) x64 Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz
Memory: 94.53 MB / 16.00 GB
Shell: 5.3 - /bin/zsh
Binaries:
Node: 10.12.0 - ~/.nvm/versions/node/v10.12.0/bin/node
Yarn: 1.16.0 - ~/.nvm/versions/node/v10.12.0/bin/yarn
npm: 6.9.0 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 12.1, macOS 10.14, tvOS 12.1, watchOS 5.1
Android SDK:
API Levels: 23
Build Tools: 23.0.1
IDEs:
Xcode: 10.1/10B61 - /usr/bin/xcodebuild
npmPackages:
react: 16.8.3 => 16.8.3
react-native: 0.59.8 => 0.59.8
npmGlobalPackages:
react-native-cli: 2.0.1
react-native-git-upgrade: 0.2.7
Steps to Reproduce
- Make a list (FlatList or Array.map, it happens with both)
- The renderItem should get an onPress event
- The onPress event changes the style to a high zIndex and position absolute
Expected Behavior
I expect that the component with the high zIndex is over every other component.
Actual Behavior
It seems like it ignores the zIndex property. The behavior is exactly like I would not apply any zIndex. I can remove the zIndex and I get the same result. Google Drive Link to a screenshot.
Reproducible Demo
Github Demo Project rn Branche This is just an extract out of my current rn project. Expo Link (Not on the latest rn version) Google Drive Video which show the issue
I was about to open a proposal on this, but might be better to just discuss in this issue.
I came across the same problem and worked around it by adding an additional cellStyle
prop to my FlatList
component. I then added this cellStyle
prop to the styles array generated by CellRenderer
in VirtualizedList
.
Setting the zIndex
to the parent element generated by CellRenderer
works as you'd expect.
Happy to put in a PR if this seems like an acceptable solution.
@TheNoim For the time being you could use patch-package to make the same change in this commit: https://github.com/mattmcdonald-uk/react-native/commit/a59888b9b68698985b784b6ee29a80c9b878e28d
@mattmcdonald-uk Thanks for the solution, but I can't use it. I tried to modify your attempt (mattmcdonald-uk/react-native@a59888b). In my example repo I use a wrapper component which can't have the cellStyle prop and I tried to access the applied style with other methods, but I failed. It is a workaround but not a final solution. This should really get fixed.
Off topic: react-native-bot 1, @hramos 0 :D Just kidding.
Having the same issue here
Will we ever get a fix for this? I mean, this is the second issue about this and still: nothing
As far as I can tell, no PRs have been submitted to address this issue. I'm adding the Help Wanted tag to surface the issue more broadly.
Thanks for posting this! It looks like your issue may refer to an older version of React Native. Can you reproduce the issue on the latest release, v0.55?
Thank you for your contributions.
No need to override any React Native internals to set zIndex
on the item wrapper views of a FlatList
, here’s how I achieved it;
<FlatList
data={timeline}
renderItem={this.getItemView}
CellRendererComponent={({ children, index, style, ...props }) => {
const cellStyle = [
style,
// I want each item to have a higher zIndex than the previous one,
// in reversed order due to the FlatList being inverted
{ zIndex: this.state.timeline.length - index }
]
// OverflowableView for Android...
return (
<OverflowableView style={cellStyle} index={index} {...props}>
{children}
</OverflowableView>
)
}}
inverted />
@Haraldson It could solve my exact case (Not tested), but the not the core problem with zIndex in a List. We can consider this as an workaround. @react-native-bot Still there in v0.55. Source
@Haraldson That workaround looks reasonable, but unfortunately when I override CellRendererComponent
, handling of keys seems to break, even if I pass the same key to the first child returned in CellRendererComponent
. Any advice there?
@isaachinman I don’t quite get the problem? key
should be part of props
, which is spread into the Cell view.
@Haraldson Let me explain.
Generally speaking, I am attempting to animate the reorder of items within a FlatList
using LayoutAnimation
. Here is the simplest possible example of that, working just fine.
The problem I've run into is that depending on the direction an item is moving (up or down), it will animate behind the other items, as it is after them in the literal JSX order.
So, I want to increase the zIndex/elevation of an item just when it is animating. Which is how I arrived at this thread. Here's the same example, but using the most basic version of your CellRendererComponent
example. The animation is now broken, despite the keys being present and remaining identical.
Even if I only return children directly, the animation breaks due to full re-renders of everything.
Hopefully this is clear... I have no idea what's going on here.
I think this issue should definitely get fixed. A workaround would be ok, but I would prefer something by the core team of rn.
Hello there 👋 this issue seems to have been inactive for the past few months. Because of this, it's likely that the issue is not a high priority anymore or it has been solved by OP; for these reasons, we'll close it.
But please, if it's actually still an issue with 0.59 please comment below and we can reopen it or please send us a Pull Request with a fix 😊
@kelset Issue still persists.
Can you submit a repro?
I did. In the initial issue. I updated the repo.
The one submitted above is using RN 0.54 (https://github.com/TheNoim/zIndexBug/blob/3e36101903ab96841ba4841e6db214cb4a7df50e/package.json#L18)- as I mentioned when I closed the issue, we'd need one with 0.59
went through the hassle and updated to 0.59
@kelset I proved, it is still an issue. Please reopen it again.
sorry, I've missed the other comment. Reopening.
@kelset Hello. Could you tell me please, what we can do with issue? I`m trying to make this case in android and I have bad result - the ScrollView is under it.... ()
@KassoBrapik Not sure if this is the same issue.
@TheNoim is there any way to position fix element inside ScrollView ?
I am experiencing the following issue only with android.
View
disappears when rendered inside a FlatList
and have position: 'absolute'
In the example below the Locations component renders a FlatList
class Locations extends Component {
renderCard(item, index) {
return (
<Location location={item} />
)
}
render() {
const { locations } = this.state
return (
<FlatList
data={locations}
renderItem={({ item, index }) => this.renderCard(item, index)}
/>
)
}
}
The Location Component renders a View
class Location extends Component {
render() {
<View style={styles.container}>
<Text>Test</Text>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'red',
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
}
})
If I remove flatlist the Red View with the Text on top is displayed.
If I add the flatlist, the Red View and text element are not displayed.
I was able to avoid this issue by wrapping the view inside a container view like this:
class Location extends Component {
render() {
<View style={{height: 100, width: 100}}>
<View style={styles.container}>
<Text>Test</Text>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'red',
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
}
})
the example is based on rn 0.54.3 https://github.com/TheNoim/zIndexBug/blob/rn/package.json#L18
There is another example based on rn 0.59 https://github.com/TheNoim/zIndexBug/blob/master/package.json#L12
I am not sure if the original issue reproduces on latest react-native version and on android, there are several workaround for fixing zIndex issues and they can be adopted in this use case.
I tried to test the above issue in the react native master branch. During the implementation of the example I noticed that @TheNoim added dependencies like 'react-native-material-cards'
that are not part of the react-native library. I believe that reproducible examples should not include dependencies other then react-native...
No need to override any React Native internals to set
zIndex
on the item wrapper views of aFlatList
, here’s how I achieved it;<FlatList data={timeline} renderItem={this.getItemView} CellRendererComponent={({ children, index, style, ...props }) => { const cellStyle = [ style, // I want each item to have a higher zIndex than the previous one, // in reversed order due to the FlatList being inverted { zIndex: this.state.timeline.length - index } ] // OverflowableView for Android... return ( <OverflowableView style={cellStyle} index={index} {...props}> {children} </OverflowableView> ) }} inverted />
This particular code causes a crash on android react native 62.2... So its no longer a valid workaround.
No need to override any React Native internals to set
zIndex
on the item wrapper views of aFlatList
, here’s how I achieved it;<FlatList data={timeline} renderItem={this.getItemView} CellRendererComponent={({ children, index, style, ...props }) => { const cellStyle = [ style, // I want each item to have a higher zIndex than the previous one, // in reversed order due to the FlatList being inverted { zIndex: this.state.timeline.length - index } ] // OverflowableView for Android... return ( <OverflowableView style={cellStyle} index={index} {...props}> {children} </OverflowableView> ) }} inverted />
This workaround worked as I expected, but when I do this onEndReached is not called, so FlatList doesn't load more data. Anyone having this problem?
Here is my code:
const CellRendererComponent = (props: any) => {
const { children } = props
const [isSwipingCell, setIsSwipingCell] = useState(false)
const onSwipeStart = () => {
setIsSwipingCell(true)
}
const onSwipeEnd = () => {
setIsSwipingCell(false)
}
return (
<View
style={{
zIndex: isSwipingCell ? 100 : 0,
flexDirection: 'row',
width: size.screenWidth,
}}>
{React.cloneElement(children[0].props.children[0].props.children, {
onSwipeStart: onSwipeStart,
onSwipeEnd: onSwipeEnd,
})}
{children[0].props.children[1] &&
React.cloneElement(children[0].props.children[1].props.children, {
onSwipeStart: onSwipeStart,
onSwipeEnd: onSwipeEnd,
})}
</View>
)
}
export default function LikeList() {
const [data, setData] = useState(DATA)
const onSwipeSuccess = (id: string) => {
setData(_data => _data.filter(item => item.id !== id))
}
const renderItem = useCallback(({ index, item }) => {
return (
<MovingCard
index={index}
data={item}
onSwipeSuccess={onSwipeSuccess}
onSwipeStart={undefined}
onSwipeEnd={undefined}
/>
)
}, [])
const keyExtractor = useCallback(item => {
return item.id
}, [])
return (
<View
style={{
flex: 1,
backgroundColor: color.background.primary,
}}>
<FlatList
data={data}
CellRendererComponent={CellRendererComponent}
renderItem={renderItem}
keyExtractor={keyExtractor}
numColumns={2}
horizontal={false}
/>
</View>
)
}
Couldn't make this workaround work on Android without also having removeClippedSubviews={false}
explicitly set.
Couldn't make this workaround work on Android without also having
removeClippedSubviews={false}
explicitly set.
It's working, thank you.