GithubHelp home page GithubHelp logo

Comments (6)

eps1lon avatar eps1lon commented on April 20, 2024

As far as I an tell this also repros without toggling disabled: https://codesandbox.io/s/react-canary-radio-buttons-forked-ydjdlp?file=/src/App.js

So it's just about changing the controlled checked delayed.

from react.

Luk-z avatar Luk-z commented on April 20, 2024

The problem was introduced with 18.3.0-next-1f248bdd7-20230419. The previous version 18.3.0-next-d962f35ca-20230418 works.

from react.

robrichard avatar robrichard commented on April 20, 2024

It looks like it was this change that introduced this bug: #26667

from react.

kambleaa007 avatar kambleaa007 commented on April 20, 2024

what are ways to fix this issue?

from react.

zhengjitf avatar zhengjitf commented on April 20, 2024

FYI, I find something by investigating, as below:

extractEvents:

const inst = getTargetInstFunc(domEventName, targetInst);
if (inst) {
createAndAccumulateChangeEvent(
dispatchQueue,
inst,
nativeEvent,
nativeEventTarget,
);
return;
}

onChange isn't called because inst here is falsy in that process. PS: In our case, getTargetInstFunc should be equal to getTargetInstForClickEvent.

Diving into the inner functions as the followings.

getTargetInstForClickEvent:

function getInstIfValueChanged(targetInst: Object) {
const targetNode = getNodeFromInstance(targetInst);
if (updateValueIfChanged(((targetNode: any): HTMLInputElement))) {
return targetInst;
}
}

updateValueIfChanged:

const lastValue = tracker.getValue();
const nextValue = getValueFromNode(node);
if (nextValue !== lastValue) {
tracker.setValue(nextValue);
return true;
}
return false;

tracker:

const tracker = {
getValue() {
return currentValue;
},
setValue(value: string) {
if (__DEV__) {
checkFormFieldValueStringCoercion(value);
}
currentValue = '' + value;

We can find the key is that the tracked value should be different from the value get from node (getValueFromNode(node)) in our case. We can believe the tracked value was not updated after the delayed state change, which cause the issue.

Analysis by reproduction steps (Please visit this demo, which can print the tracked values):

  1. Initially:
    • One: checked (getValueFromNode(node) is 'true'), and the tracked value is 'true'
    • Two: unchecked, and the tracked value is 'false'
  2. Click 'Two', and wait for delayed setValue: onChange is called
    • One: unchecked, and the tracked value is 'false'
    • Two: checked, and the tracked value is 'true'
  3. Click 'One', and wait for the delayed setValue: onChange is called
    • One: checked, and the tracked value is 'true'
    • Two: unchecked, and the tracked value is 'true'
  4. Click 'Two', won't call onChange again

PS: The tracked value can be updated at the end of the event handler (by restoreControlledInputState), so Step 2 will result in the correct tracked values.

So, I think one solution is to update the tracked value (at the end of the commit mutation phase) when the checked prop changes.

I'd like to submit a PR to fix it. Any corrections or suggestions will be appreciated, (for I'm not sure if I miss anything important).

from react.

Luk-z avatar Luk-z commented on April 20, 2024

I tried another way to understand what caused the bug.

I just checked the diff between a working commit (d962f35) and non-working commit (1f248bd) and figured out that the bug happens after removing this lines of code in updateProperties() function of packages/react-dom-bindings/src/client/ReactDOMComponent.js.

just restoring

              const checkedValue = nextProps.defaultChecked;
              const inputElement: HTMLInputElement = (domElement: any);
              inputElement.checked =
                !!checkedValue &&
                typeof checkedValue !== 'function' &&
                checkedValue !== 'symbol';

or just adding domElement.checked = checked; the bug disappear.

Maybe the problem is explained in this comment

 * If `checked` or `value` are not supplied (or null/undefined), user actions
 * that affect the checked state or value will trigger updates to the element.
 *
 * If they are supplied (and not null/undefined), the rendered element will not
 * trigger updates to the element. Instead, the props must change in order for
 * the rendered element to be updated.

inputElement.checked is not updated and will result null/undefined and the radio is no more controlled?

You can check this branch. I've also made a change to packages/react-devtools-shell/src/e2e-apps/ListApp.js to start devtools server with a simple radio example.
To run the server:

  • run yarn in the root directory and in packages/react-devtools-inline directory.
  • from to the root directory run yarn build-for-devtools
  • from packages/react-devtools-shell folder execute yarn start (better to open another shell for this command)
  • go to http://localhost:8080/e2e.html
React.b.mov

from react.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.