Appearance
Built-in React Components
FreshReact provides several built-in components you can use in your JSX.
Fragment (<>...</>)
Lets you group elements without a wrapper DOM node:
jsx
function Post() {
return (
<>
<PostTitle />
<PostBody />
</>
);
}Equivalent to <Fragment>...</Fragment>. Use the explicit <Fragment> form when you need a key:
jsx
function Blog({ posts }) {
return posts.map(post => (
<Fragment key={post.id}>
<PostTitle title={post.title} />
<PostBody body={post.body} />
</Fragment>
));
}StrictMode
Enables additional development-only checks for the component tree inside it:
jsx
import { StrictMode } from 'react';
function App() {
return (
<StrictMode>
<Header />
<Main />
<Footer />
</StrictMode>
);
}Strict Mode enables these checks in development:
- Components re-render an extra time to find impure rendering bugs
- Effects run an extra cleanup+setup cycle to find missing cleanup
- Code is checked for usage of deprecated APIs
INFO
There is no way to opt out of Strict Mode inside a tree wrapped by it. This gives you confidence that all components inside are checked.
Suspense
Displays a fallback while child components are loading:
jsx
import { Suspense } from 'react';
function App() {
return (
<Suspense fallback={<Loading />}>
<Albums />
</Suspense>
);
}Props:
children- The actual UI you intend to render. Ifchildrensuspends while rendering, the Suspense boundary switches tofallback.fallback- An alternate UI to render while the actual UI is loading.
Nested Suspense Boundaries
jsx
<Suspense fallback={<BigSpinner />}>
<Biography />
<Suspense fallback={<AlbumsGlimmer />}>
<Panel>
<Albums />
</Panel>
</Suspense>
</Suspense>React will display the closest parent Suspense boundary's fallback. This lets you nest Suspense boundaries to create a loading sequence.
Suspense with Server Components
jsx
import { Suspense } from 'react';
async function ConferencePage({ slug }) {
const conf = await db.Confs.find({ slug });
return (
<ConferenceLayout conf={conf}>
<Suspense fallback={<TalksLoading />}>
<Talks confId={conf.id} />
</Suspense>
</ConferenceLayout>
);
}
async function Talks({ confId }) {
const talks = await db.Talks.findAll({ confId });
return <SearchableVideoList videos={talks.map(t => t.video)} />;
}Profiler
Measures rendering performance of a React tree programmatically:
jsx
import { Profiler } from 'react';
function App() {
return (
<Profiler id="App" onRender={onRender}>
<Navigation />
<Main />
</Profiler>
);
}
function onRender(id, phase, actualDuration, baseDuration, startTime, commitTime) {
console.log(`${id} ${phase} render took ${actualDuration}ms`);
}onRender parameters:
id- The stringidof the Profilerphase-"mount","update", or"nested-update"actualDuration- Milliseconds spent renderingbaseDuration- Estimated render time without memoizationstartTime/commitTime- Timestamps
WARNING
Profiling adds some overhead. It is disabled in production builds by default.
Activity (Experimental)
Lets you hide and show parts of the UI:
jsx
import { Activity } from 'react';
function TabContainer({ activeTab }) {
return (
<div>
<Activity mode={activeTab === 'posts' ? 'visible' : 'hidden'}>
<PostsTab />
</Activity>
<Activity mode={activeTab === 'photos' ? 'visible' : 'hidden'}>
<PhotosTab />
</Activity>
</div>
);
}When mode is "hidden", the component is hidden from the DOM but its state is preserved. This is useful for tab containers where you want to keep state alive.