The form element is the future of React

Please think about a question: If there is a HTMLlabel and Reacttwo labels are created around it hook, then this label Reactmust be very important to future development. Is there anything wrong with that?

This label is—— form.

ReactformThe following 2 new ones have been released hook:

  • useOptimistic
  • useFormStatus

This article will talk about the Reactsurrounding formlayout and development.

Welcome to join the human high-quality front-end exchange group and lead flying

The development history of Next.js

When talking about Reactfuture development, we must start with Next.jschatting. After all, Reactteam members either join Nextthe team or are on their way to joining.

webThe parts of development involving front-end and back-end interaction mainly include:

  1. Render front-end pages based on back-end data
  2. Save data to backend based on frontend user input

Next.jsThe development mainly revolves around the above two points.

Render front-end pages based on back-end data

In the early days, the Next.jsmain features were SSRSSGThat is to say, the process of rendering the front-end page based on the back-end data is moved from the front-end to the back-end.

Routing during this period Next.jsis called Pages Router.

The time has come Next.js v13and RSC(React Server Component) as the core has App Routerreplaced Pages Routerthe default configuration.

Many friends are not familiar with it RSCand think it is an experimental feature. In fact, RSCthe excuse Next.jshas already been implemented.

To understand in one sentence RSC– client-side components (components rendered in the browser React) can be divided into two parts based on dependencies:

  • Components that rely on data sources (such as databases and file systems) can be used as RSC(server-side components)
  • Components that depend on state (such as statepropscontext) can be used as client components

From the perspective of rendering front-end pages based on back-end data :

  • SSRSSGis at the page level (server-side rendering renders the entire page)
  • RSCIt is at the component level (the server component requests the data source)

Save data to backend based on frontend user input

After talking about rendering front-end pages based on back-end data , what optimizations can be done around saving data to the back-end based on front-end user input ?Next.js

This is Next.jsthe experimental feature that needs to be mentioned—— Server Action.

Server Action

A common scenario for saving data to the backend based on front-end user input is form submission . Usually we will do subsequent processing in the event form:obSubmit

function  Form () {
   function  submit () {
     // ...logic for processing formData 
    // ...logic for sending requests
  }
  return (
     < form  onSubmit = {submit} > 
      < input  type = "text" /> 
      < input  type = "text" /> 
    </ form >
  )
}

Is there anything that can be improved in the above code?

From a user experience perspective, if the front end is disabled JS, it Reactcannot run and the above interaction will be invalid. JSIt would be nice if the form could be submitted even when disabled .

From the perspective of development experience, submitthe method will initiate a request, and the backend will operate the database based on the request formData, which is relatively cumbersome. submitIt would be great if the database could be directly manipulated within the method.

Server ActionFeatures are designed to achieve the above two goals.

Let’s look at the first goal first.

Goal 1

HTMLThe native formelement has an actionattribute that can receive one url. When the form is submitted (such as clicking typethe submitbutton), formDatait will be submitted to this url.

< form  action = "/action_page.php"  method = "get" > 
  < label  for = "fname" > First name: </ label > 
  < input  type = "text"  id = "fname"  name = "fname" > < br > < br > 
  < label  for = "lname" > Last name: </ label > 
  < input  type = "text"  id = "lname"  name = "lname" > < br > < br > 
  < input  type = "submit "  value = "Submit" > 
</ form >

Since the behavior of submitting a formHTML is natively supported, JSit can also be executed when disabled.

This is JSthe theoretical basis for disabling the form to be submitted.

Goal 2

ReactformThe extended actionattributes allow it to not urlonly support callback functions, such as:

function  App () {
   function  submit ( data ) {
     // ...
  }
  return (
     < form  action = {submit} >
      <! -- Omitted -->
    </ form > 
  );

If this callback function contains logic executed by the front end, it is called client action, such as the following:

  async  function  submit ( data ) {
     await  const res = saveData (data);
     // ... 
  }

If this function contains logic executed by the backend, it is called server action, such as the following:

  "use server"
  
  async  function  submit ( data ) {
     const userID = cookies (). get ( "userID" )?. value ;
     await db. users . update (userID, data);
     // ... 
  }

"use server"The mark indicates that this is a 

server action.

If so server action, then the type of request initiated is multipart/form-data(i.e. form submission):

The response type is RSC:

In other words, with it server action, developers can write back-end logic directly in formthe actionattribute (or buttonthe attribute and several other attributes), and these logic can also be executed even if formActionthe browser is disabled .JS

2 new hooks

In order to provide better service server actionReactthe team has launched 2 new ones hookto improve formthe user experience in scenarios:

  • useOptimistic
  • useFormStatus

hookCurrently, the introduction of these 2 can only be seen in the Next.js documentation (not Reactthe documentation).

useOptimisticMainly used to optimize the user experience of submitting data .

For example, in the case of likes , the usual logic is:

  1. Click the like button
  2. Make a like request
  3. The like is successful and the like effect is displayed on the front end

But for the sake of smooth user experience, the front-end usually makes the logic as follows:

  1. Click the like button
  2. The front end displays the like effect (and initiates a like request at the same time)
  3. According to the request result, if the like is successful, no processing will be performed. If the like fails, the button will be reset.

useOptimisticThe essence is to achieve the above effects at the state level.

useFormStatuspendingIt is used to display status during form submission :

function  ButtonDisabledWhilePending ( {action, children} ) {
   const {pending} = useFormStatus ();
   return (
     < button  disabled = {pending}  formAction = {action} >
      {children}
    </ button >
  );
}

Some students may be wondering: useFormStatusWithout passing parameters, how does he know which one corresponds form?

In fact, in order to achieve this useFormStatus, a custom one is built Reactin the source code for all (i.e. components corresponding to HostComponentnative elements, for example) .HTML<div/>context

When a formtrigger form is submitted, contextthe value will be updated with this formdata. useFormStatusItself is just useContext(上述context).

Summarize

It can be found that, whether it is useFormStatususeOptimisticor the new ones released in the past 1 to 2 years hook(such as useIduseMutableSource), we developers rarely use them.

Because these are provided hookfor the upper-level framework (mainly ).Next.js

ReactIt has already completed its mission as a front-end framework. In the second half of his life, he will exist as the operating system of the upper framework.

server actionYes Next.jsfuture, Next.jsyes Reactfuture. Therefore, Reactthe future will formcontinue to be laid out around elements.