Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

checkbox does not update to checked state upon hydration and rerendering #29747

Closed
godmar opened this issue Oct 8, 2021 · 1 comment
Closed
Labels
bug Issue was opened via the bug report template.

Comments

@godmar
Copy link

godmar commented Oct 8, 2021

What version of Next.js are you using?

5.0.0

What version of Node.js are you using?

14.17.5

What browser are you using?

Chrome, Firefox

What operating system are you using?

Linux

How are you deploying your application?

next start

Describe the Bug

When a checkbox is rendered serverside in the unchecked state, then it remains in the unchecked state clientside even though a rendering cycle is performed where it is checked.

Consider a page in pages/min.js

import * as React from 'react';
import { useState } from 'react';
import { useRouter } from 'next/router';

export default function TestCheckbox() {
  const router = useRouter();
  const ischecked = router.query.a == "true";
  console.log(`rendering: ischecked ${ischecked}`);
  const [checked, setChecked] = useState(ischecked);
  const handleChange = (ev) => { setChecked(!checked); }
  return (
    <div>
        <input type="checkbox" 
               checked={checked} 
               onChange={handleChange} />
    </div>
  );
}

I now visit http://localhost:3000/min?a=true
In the server-side rendering process, the query object is omitted as described in issue #8259 and elsewhere. Indeed, the server return <div id="__next"><div><input type="checkbox"/></div></div>.

On the client side, I see

rendering: ischecked false
rendering: ischecked true

in the console, making me believe that the page was rehydrated and rendered with ischecked being true.

Yet, the checkbox remains unchecked.
The checkbox otherwise works fine (I can check/uncheck it) and the behavior also doesn't occur when performing intra-app page navigation. The issue seems to be tied to the hydration process.

Expected Behavior

I would expect the checkbox to be checked when the page is cold-loaded via http://localhost:3000/min?a=true, despite having been rendered in the unchecked state on the server side due to the lack of query parameters available there.

To Reproduce

A self contained example is given above. Place it in the pages folder.

@godmar godmar added the bug Issue was opened via the bug report template. label Oct 8, 2021
@ijjk
Copy link
Member

ijjk commented Oct 8, 2021

Hi, the default value of useState is not meant to be changed like that and should be updated via setChecked instead, moving the query value check inside of a useEffect works properly e.g.

import * as React from 'react';
import { useState } from 'react';
import { useRouter } from 'next/router';

export default function TestCheckbox() {
  const router = useRouter();
  const [checked, setChecked] = useState(false);
  const handleChange = (ev) => { setChecked(!checked); }
  
  React.useEffect(() => {
    if (router.query.a === "true") {
      setChecked(true)
    }
  }, [router.query.a])
  
  return (
    <div>
        <input type="checkbox" 
               checked={checked} 
               onChange={handleChange} />
    </div>
  );
}

@ijjk ijjk closed this as completed Oct 8, 2021
@vercel vercel locked and limited conversation to collaborators Oct 8, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
bug Issue was opened via the bug report template.
Projects
None yet
Development

No branches or pull requests

2 participants