Comments (8)
Hi,
I noticed this issue and I'd like to contribute to help resolve it. I have experience working with React, SVG elements, and event handling, and I believe I can assist in identifying the root cause or proposing a solution.
This will be my first time contributing to open source, so I’d appreciate any guidance on the next steps or specific areas of the codebase I should focus on. I’ll start by reproducing the issue locally and analysing the behaviour across different React versions.
Looking forward to contributing
from react.
Thank you for reporting. This is a pretty obscure bug. It requires dangerouslySetInnerHTML
and a re-render during the focus event when clicking. Not using dangerouslySetInnerHTML
or not re-rendering will work as expected.
It started breaking in https://www.npmjs.com/package/react/v/18.3.0-next-85de6fde5-20230328
First bad: https://www.npmjs.com/package/react/v/18.3.0-next-85de6fde5-20230328
Last good: https://www.npmjs.com/package/react/v/18.3.0-next-41b4714f1-20230328
Diff: 41b4714...85de6fd
Likely candidate is #26501. It's a big diff but maybe somebody is able to spot an issue.
from react.
Hi @zdravkov
I've managed to find a fix for this issue. Let me know if it aligns with the best practices for this codebase or if it could be made better/more optimized.
Inside the Element.js component:
- Added a ref to track user interaction:
const userInteractedRef = useRef(false);
- Added a useEffect to ensure the click event is not missed on the first focus:
useEffect(() => {
if (id !== null && userInteractedRef.current) {
userInteractedRef.current = false; // Reset the flag
dispatch({
type: 'SELECT_ELEMENT_BY_ID',
payload: id,
});
}
}, [id, dispatch]);
- Updated the click handler and added a focus handler to set the user interaction flag:
const handleClick = ({ metaKey }) => {
if (id !== null) {
userInteractedRef.current = true;
logEvent({
event_name: 'select-element',
metadata: { source: 'click-element' },
});
dispatch({
type: 'SELECT_ELEMENT_BY_ID',
payload: metaKey ? null : id,
});
}
};
const handleFocus = () => {
userInteractedRef.current = true;
setFocused(true);
};
- Lastly, added an onFocus property to the main div inside the return:
<div
className={className}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onMouseDown={handleClick}
onDoubleClick={handleDoubleClick}
onFocus={handleFocus}
style={style}
data-testname="ComponentTreeListItem"
data-depth={depth}>
Inside the tests/ReactDOMSVG-test.js file
Here's the test I wrote to test this out:
it('should trigger click event on first focus', async () => {
const log = [];
const handleClick = () => {
log.push('svg click');
};
function App() {
const [focused, setFocused] = React.useState(false);
const handleFocus = () => {
setFocused(true);
};
return (
<svg
onFocus={handleFocus}
tabIndex={1}
onClick={handleClick}
viewBox="0 0 512 512"
dangerouslySetInnerHTML={{
__html: '<path d="M256 352 128 160h256z" />',
}}
></svg>
);
}
const container = document.createElement('div');
document.body.appendChild(container);
const root = ReactDOMClient.createRoot(container);
try {
await act(() => {
root.render(<App />);
});
const svgElement = container.querySelector('svg');
svgElement.focus();
// Simulate click event
const clickEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
});
svgElement.dispatchEvent(clickEvent);
expect(log).toEqual(['svg click']);
} finally {
document.body.removeChild(container);
}
});
});
Output:
And here are the results after running the test:
koushikjoshi@Koushiks-MacBook-Pro react % yarn test packages/react-dom/src/__tests__/ReactDOMSVG-test.js
yarn run v1.22.21
$ node ./scripts/jest/jest-cli.js packages/react-dom/src/__tests__/ReactDOMSVG-test.js
$ NODE_ENV=development RELEASE_CHANNEL=experimental compactConsole=false node ./scripts/jest/jest.js --config ./scripts/jest/config.source.js packages/react-dom/src/__tests__/ReactDOMSVG-test.js
Running tests for default (experimental)...
PASS packages/react-dom/src/__tests__/ReactDOMSVG-test.js
ReactDOMSVG
✓ creates initial namespaced markup (107 ms)
✓ creates elements with SVG namespace inside SVG tag during mount (17 ms)
✓ creates elements with SVG namespace inside SVG tag during update (7 ms)
✓ can render SVG into a non-React SVG tree (1 ms)
✓ can render HTML into a foreignObject in non-React SVG tree (1 ms)
✓ should trigger click event on first focus (9 ms)
Test Suites: 1 passed, 1 total
Tests: 6 passed, 6 total
Snapshots: 0 total
Time: 0.762 s
Ran all test suites matching /packages\/react-dom\/src\/__tests__\/ReactDOMSVG-test.js/i.
✨ Done in 1.51s.
Let me know if this looks good enough for me to make a PR.
Please note- I only ran the ReactDOMSVG-test to ensure nothing breaks, but if you think that there are tests elsewhere that could potentially break, let me know and I'll run a full test too.
Looking forward to your feedback!
from react.
Thank you for your help with the issue and the contribution, I am not quite familiar with the code rules of this repo, so I can't provide good opinion on your pr. I hope somebody from the core team will check it soon! :)
Greetings!
from react.
Hi,
I noticed this issue, const [focused, setFocused] = React.useState(true); // I made the value changes from false to true.
Now it is working
import * as React from 'react';
const App = () => {
const [focused, setFocused] = React.useState(true);
const handleFocus = () => {
setFocused(true);
};
return (
<svg
onFocus={handleFocus}
tabIndex={1}
onClick={() => {
console.log('svg click');
}}
viewBox="0 0 512 512"
dangerouslySetInnerHTML={{
__html: '',
}}
>
);
};
export default App;
from react.
@nareshmurty - Indeed, this is part of the bug scenario - the issue is observed when any change of the state is attempted in the onFocus event - it should be possible to change the state in this event and currently it is not.
from react.
@zdravkov - I got a solution related to the above scenario but I don't know whether it is the best way or not.
- Using the setTimeout(), may be we can delay the state update, here it is working fine during state change
import * as React from 'react';
const App = () => {
const [focused, setFocused] = React.useState(false);
const handleFocus = () => {
setTimeout(() => {
setFocused(true);
console.log(focused);
}, 500);
};
return (
<svg
onFocus={handleFocus}
tabIndex={1}
onClick={() => {
console.log('svg click');
}}
viewBox="0 0 512 512"
dangerouslySetInnerHTML={{
__html: '',
}}
>
);
};
export default App;
from react.
@nareshmurty thank you for your efforts! The suggested approach rather seems like a workaround than a solution to me. A solution here would be fixing the bug in the new React 19 codebase.
from react.
Related Issues (20)
- Bug: Wrong detection of non-boolean attribute when working with React API HOT 2
- Cannot find name 'dialog' HOT 2
- Bug: useMemo has a problem of executing multiple times without changing dependencies HOT 2
- Bug: bug de teste
- [React 19] Export SuspenseException HOT 2
- [React 19] - `ReactElement` created from `React.createElement` are not renderable anymore HOT 3
- [Compiler Bug]: function parameter inside component override outer parameter incorrectly
- forceUpdate not work in child component GuardGraph
- [React 19] useOptimistic is not updating its optimistic collection immediately HOT 6
- Bug: useEffect and Event Handler Timing Regressions in React 18 Legacy Mode HOT 1
- [DevTools Bug]: No way to debug suspense events
- [Compiler Bug]: setState in useEffect / react compiler and eslint hooks plugin HOT 1
- [DevTools Bug] Cannot add node "20468" because a node with that id is already in the Store. HOT 1
- [Help Wanted] How can I become a member of reactjs? HOT 1
- [React 19]useEffect cleaned the wrong state in StrictMode HOT 7
- Inability to prioritise hydration & react yields too willingly HOT 2
- [DevTools Bug]: Script tag connection method not working in 6.0.0 HOT 1
- Bug: DevTools 6.0.0 element inspector not working with React Native 0.75 HOT 1
- Bug: re-rendering order of onBlur and onClick inconsistent between desktop and mobile browsers HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react.