Skip to content
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

Bug: unmount component with creating element JSX variable #23398

Open
parkhojeong opened this issue Mar 2, 2022 · 2 comments
Open

Bug: unmount component with creating element JSX variable #23398

parkhojeong opened this issue Mar 2, 2022 · 2 comments

Comments

@parkhojeong
Copy link

@parkhojeong parkhojeong commented Mar 2, 2022

React version: 17.0.2

Steps To Reproduce

  1. type and run below code example
  2. click change button

Link to code example:
https://codesandbox.io/s/unmount-issue-when-prop-changed-yn12l0

const A = ({ val }: { val?: string }) => {
  const [num, setNum] = useState(0);
  useEffect(() => {
    setTimeout(() => {
      setNum(10);
    }, 5000);

    return () => {
      console.log('unmounted');
    };
  }, []);

  return (
    <>
      <div>{num}</div>
      <div>{val}</div>
    </>
  );
};

function App(): JSX.Element {
  const [str, setStr] = useState('');
  const ValA = () => {
    return <A val={str} />;
  };
  return (
    <>
      <ValA />
      <button
        type={'button'}
        onClick={() => {
          setStr('changed');
        }}
      >
        change
      </button>
    </>
  );
}

image
fail case above image is case for my issue

The current behavior

App show 10 after 5000ms from first render.
if i click change button, it makes unmount A.

The expected behavior

i want A component only rerendering after click change
in diffing algorithm (https://reactjs.org/docs/reconciliation.html), unmount will be triggered by changing tag name. i wonder why A Component is unmounted.

@nmain
Copy link

@nmain nmain commented Mar 2, 2022

<ValA /> is remounted every time <App /> renders because it's a local function. React has no way of knowing when different functions are really the same; all it can do is === compare ValA to the previous ValA and see that these are different components. Since ValA doesn't close over anything, it should be moved to an outer scope.

<A /> is remounted every time <App /> rerenders because when reconciliation finds a completely different component type at a particular node (as was the case for ValA here), no attempt is made to reconcile any children of that. In general, if two components are completely different, there's no expectation that the children they produce would be similar and recursively reconciling under them is not a productive use of time.

@parkhojeong
Copy link
Author

@parkhojeong parkhojeong commented Mar 3, 2022

babel result isReact.createElement(ValA, null). so, is tag name(react reconcile document say ) same with variable name every re-render?
i expect name of variable ValA is used for tag name that diffing algorithm say.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants