New use & useOptimistic hooks in React package
Mon Feb 26 2024
There are two new hooks added to the React package, which is still experimental as of the writing of this blog. This hook allows for progressive improvements to the UI for server and client interactions.
use hook
use
is a React Hook that lets you read the value of a resource
like a Promise
or context
. You can just
call this hook inside of your component and pass a promise or context and it
What distinguishes this hook from others is that it may be invoked within loops,
conditionals, or any block. However, it is still necessary to call components
and hooks exclusively. will return you a value.
const value = use(resource);
Usage
Reading context values.
The use hook is similar to the useContext hook in that it accepts a Context and returns a value if that component is wrapped in the Context, but it may be used inside conditionals and loops, making it more powerful than useContext. React recommends this hooks over useContext because they are more versatile.
"use client";
import ThemeContext from "@/contexts";
import Button from "@/components";
export default function GetStartedButton({ newUI, children }) {
if (newUI) {
const theme = use(ThemeContext); // hook inside if condition
return <Button theme={theme}>{children}</Button>;
}
return <button>{children}</button>; //simple button
}
Stream data from server to client.
A Promise can be passed from a Server Component to a Client Component and resolved in the Client Component with the use Hook. You can also resolve the Promise in a Server Component with await
and pass the required data to the Client Component as a prop.
export default async function Home() {
const feeds = await getFeed();
const trends = await getTrends();
return (
<div>
<Feed data={feeds} />
<Explore data={trends} />
</div>
);
}
But using await
in a Server Component will block its rendering until the await
statement is finished. Passing a Promise from a Server Component to a Client Component prevents the Promise from blocking the rendering of the Server Component.
export default async function Home() {
const feedsPromise = getFeed();
const trendsPromise = getTrends();
return (
<div>
<Suspense fallback="Loading feed...">
<Feed data={feedsPromise} />
</Suspense>
<Suspense fallback="Loading trends...">
<Explore data={trendsPromise} />
</Suspense>
</div>
);
}
export default async function Feed({data}) {
const resolvedData=use(data)
return ...
}
The use
hook auto integrates with Suspense and Error boundaries when promise is resolve it shows the fallback and when error occured in promise the Error boundary can handle the error.
Note :
See it to it that the promise value should be JSON serializable when passed from server to client promise
useOptimistic hook
UseOptimistic is a React Hook that allows you to optimistically update the UI. When you do an async operation on the client side and wait for the server to react, rather than blocking the UI with a spinner, you can optimistically load the appropriate UI, and when the async task is completed, the real data is displayed.
const [optimisticState, addOptimistic] = useOptimistic(state, updateFn);
Usage
Optimistically updating forms.
export default function MessagesContainer({ messages, send }) {
const [optimisticMessages, addMessage] = useOptimistic(messages,
(state,newMessage)=>({...state,newMessage})
);
const [inputMessage, setInputMessage] = useState("");
function handleSend(){
const message=inputMessage;
setInputMessage("");
addMessage({
body:message,
pending:true,
key:uuid()
})
await send(message);
}
return (
<div>
{messages.map((message) => (
<Message {...message} />
))}
<div>
<input value={inputMessage} onChange={(e) => setInputMessage(e.target.value)} />
<button onClck={handleSend}>Send</button>
</div>
</div>
);
}
function Message({body,pending}){
return <p>{body} {pending && " - sending..."}</p>
}
So, when you create a message and send it, the message with the suffix sending appears optimistically in the UI, improving the user experience, and when the revalidated message arrives from the parent, the pending will no longer be present.