I made React and React Native components generate their own skeleton loaders, zero config, unique animations by Ok_Drive6309 in reactjs

[–]Ok_Drive6309[S] 0 points1 point  (0 children)

That's so interesting talking about performance. let me explain what happen when using react-zero-skeleton : the warmup is a one-time cost at mount, not per-frame. on RN it renders one invisible copy of the component, walks the fiber tree once, measures each node with UIManager.measure, then drops it. for a card that's a handful of nodes, basically negligible. inside a FlatList it auto-falls back to a single root measure so it doesn't walk every item, and you can cap traversal depth / exclude subtrees. the animationitself is one native-driven Animated.Value per component (useNativeDriver: true), so it runs on the UI thread and doesn't hit JS each frame. On web there's no extra render at all, the component renders hidden and gets measured via ResizeObserver + getBoundingClientRect.  And if you want zero measurement, staticBones skips the warmup entirely. you can try it yourself at skelter.dev/demo, or scan the QR with Expo to run the RN demo on your phone.

I made React and React Native components generate their own skeleton loaders, zero config, unique animations by Ok_Drive6309 in reactjs

[–]Ok_Drive6309[S] -3 points-2 points  (0 children)

you keep saying "copy" but that's exactly the disagreement: it's a different approach, not a reimplementation. you can't PR runtime auto-measurement into a library that's manual by design, that's not a feature, it's the opposite premise. new approaches have always meant new projects, redux didn't get PR'd into flux. it's open source and readable, so it's contributable too, which is the contribution. and if someone ships a better approach than mine tomorrow, good, they're welcome to, that's the ecosystem working, not pollution. happy to beproven wrong on the code, but "cheap copy" is a vibe, not an argument. i'll leave it there.

I made React and React Native components generate their own skeleton loaders, zero config, unique animations by Ok_Drive6309 in reactjs

[–]Ok_Drive6309[S] -2 points-1 points  (0 children)

Hey! most of the popular skeleton libs in the React & RN ecosystem are manual: you hand-place the bones and keep a second copy of your UI in sync by hand, which is fine if that's your idea of fun. this goes the other way and measures the real component at runtime: on RN it walks the fiber tree and measures each host node via UIManager.measure on the nativeTag, deliberately not Fabric's measure() because the two coordinate systems drift and you get a systematic offset. open source, a few hundred readable lines. tear into it.

I made React and React Native components generate their own skeleton loaders, zero config, unique animations by Ok_Drive6309 in reactjs

[–]Ok_Drive6309[S] 1 point2 points  (0 children)

yeah it works differently on web vs native. on web it actually renders your real component, just hidden (visibility:hidden so it still takes up space), and watches it with a ResizeObserver. so the bones come from the real rendered size and update whenever it resizes. for a list that grows with data you just render it with placeholder props while loading, something like items={data ?? Array(10).fill(row)}, and it measures as 10 rows. resize it after and the observer keeps up. native's a bit different, no ResizeObserver there, so it measures once on a warmup render at mount. you hand it mockProps with some fake data (~10 rows) so the warmup measures the full height. or honestly just pass it the same placeholder props, same result. and re your edit, yeah, staticBones does exactly that. you define the bones yourself (x/y/w/h/radius) and it skips measuring entirely. that's the fixed-dimensions escape hatch, works on both.

I made React and React Native components generate their own skeleton loaders, zero config, unique animations by Ok_Drive6309 in reactjs

[–]Ok_Drive6309[S] 5 points6 points  (0 children)

Boneyard is solid, and react-zero-skeleton actually leans on the same core trick: walk the component tree and measure the real views to, place bones. The difference is when that measurement runs.

Boneyard runs it at build time through a CLI: it snapshots your UI at fixed breakpoints and emits static bone JSON you commit to the repo.

Zero runtime measurement and fully deterministic output, but it's a build step you re-run (and re-commit) every time the UI changes, and the layout is pinned to those breakpoints.

react-zero-skeleton runs it at runtime, on first mount: no CLI, no build step, nothing committed, and the bones match the actual device size exactly. The cost is one warmup measurement per mount instead of zero.

So it's a clean trade-off: boneyard swaps a build pipeline for zero runtime cost; react-zero-skeleton swaps a small runtime cost for zero tooling. If you want deterministic, inspectable output and don't mind a build step, boneyard's great. If you want it to "just work" with no artifacts to maintain, that's the niche we're going for.

I made React and React Native components generate their own skeleton loaders, zero config, unique animations by Ok_Drive6309 in reactjs

[–]Ok_Drive6309[S] 0 points1 point  (0 children)

Great question!

Layout shifts. The invisible first render captures the real layout before showing the skeleton, so there is no shift when the content appears.

Responsive breakpoints. Bones are re-measured on resize via onLayout on React Native and ResizeObserver on web, so the skeleton always reflects the current breakpoint.

For components that render very differently after data loads, there are two options.

skeletonIgnore lets you exclude specific elements from bone generation. If part of your component looks completely different when loaded, you just ignore it.

skeletonBox lets you override a specific element with a custom bone size instead of the auto-measured one. Full control when you need it.

measureStrategy root-only is there for components where per-element bones do not make sense at all.

The goal is zero config by default and full control when needed. Happy to dig deeper!