question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Box clone ignores SyntheticEvent

See original GitHub issue

Adding clone property to Box component will cause SyntheticEvent to break. It’s actually passing styling props and nothing more.

  • This is not a v0.x issue.
  • I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior 🤔

Clone should also pass events and everything else that react expects on react component.

Current Behavior 😯

Box only passes className props to children when it’s cloned.

Steps to Reproduce 🕹

https://codesandbox.io/s/box-clone-problem-lmrrt?fontsize=14

Context 🔦

We are trying to wrap SvgIcon with box so we can override colors that SvgIcon supports. And also box have several useful properties that we basically decided to apply it to our icons. Something like below, but we faced the issue that when we clone the Box it won’t apply props to the child component. So we have to extract those events and apply them directly to SvgIcon.

// @flow
import React from 'react';
import PropTypes from 'prop-types';
import SvgIcon from '@material-ui/core/SvgIcon';
import Box from '@material-ui/core/Box';
import type { IconWrapperPropTypes } from './types';

function IconWrapper({
  color,
  children,
  classes,
  component,
  fontSize,
  htmlColor,
  shapeRendering,
  titleAccess,
  width,
  height,
  viewBox,
  onClick,
  onTouchEnd,
  onMouseDown,
  ...rest
}: IconWrapperPropTypes) {
  const svgColor =
    color === 'primary' ||
    color === 'secondary' ||
    color === 'inherit' ||
    color === 'action' ||
    color === 'error' ||
    color === 'disabled'
      ? color
      : undefined;
  return (
    <Box clone color={color} {...rest}>
      <SvgIcon
        width={width}
        height={height}
        viewBox={viewBox}
        component={component}
        fontSize={fontSize}
        classes={classes}
        htmlColor={htmlColor}
        shapeRendering={shapeRendering}
        titleAccess={titleAccess}
        color={svgColor}
        onClick={onClick}
        onTouchEnd={onTouchEnd}
        onMouseDown={onMouseDown}
      >
        {children}
      </SvgIcon>
    </Box>
  );
}

IconWrapper.propTypes = {
  children: PropTypes.node.isRequired,
};

export default IconWrapper;

Your Environment 🌎

Tech Version
Material-UI v4.1.3
React v16.8.6

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
RostyslavKravchenkocommented, Aug 4, 2019

I can do this something like this. Do we need to pass filteredProps into cloned elements?

--- a/packages/material-ui-styles/src/styled/styled.js
+++ b/packages/material-ui-styles/src/styled/styled.js

const classes = useStyles(props);
const className = clsx(classes.root, classNameProp);

+ let spread = other;
+ if (filterProps) {
+    spread = omit(spread, filterProps);
+ }

if (clone) {
     return React.cloneElement(children, {
         className: clsx(children.props.className, className),
+         ..spread,
     });
}

-  let spread = other;
-  if (filterProps) {
-     spread = omit(spread, filterProps);
-  }

if (typeof children === 'function') {
    return children({ className, ...spread });
}

Also, I think I can add a new unit test for this case

--- a/packages/material-ui-styles/src/styled/styled.test.js
+++ b/packages/material-ui-styles/src/styled/styled.test.js

describe('prop: clone', () => {
+  let wrapper;

+  before(() => {
+     wrapper = mount(
+       <StyledButton clone data-test="enzyme">
+          <div>Styled Components</div>
+        </StyledButton>,
+    );
+ });

+  it('should be able to pass props to cloned element', () => {
+     assert.strictEqual(wrapper.find('div').props()['data-test'], 'enzyme');
+  });

    it('should be able to clone the child element', () => {
-      let wrapper = mount(
-        <StyledButton clone data-test="enzyme">
-          <div>Styled Components</div>
-        </StyledButton>,
-    );
        assert.strictEqual(wrapper.getDOMNode().nodeName, 'DIV');
        wrapper.setProps({
           clone: false,
        });
        assert.strictEqual(wrapper.getDOMNode().nodeName, 'BUTTON');
    });
  });

@oliviertassinari, what do you think about that?

0reactions
oliviertassinaricommented, Aug 4, 2019

Looks good to me, but keep in mind that we will remove the clone prop in v5.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Box clone ignores SyntheticEvent #16475 - mui/material-ui
Adding clone property to Box component will cause SyntheticEvent to break. It's actually passing styling props and nothing more.
Read more >
Clone an instance of react's synthetic event - Stack Overflow
My concern is that by cloning only the native event the code base is dealing with two different types of events: the SyntheticEvent...
Read more >
Breaking changes in v5, part two: core components - Material UI
The clone prop was removed because its behavior can be obtained by applying the sx prop directly to the child if it is...
Read more >
React Tutorial for Beginners - SyntheticEvent - Morioh
This reference guide documents the SyntheticEvent wrapper that forms part of React's Event System. See the Handling Events guide to learn more. Overview....
Read more >
Hooks FAQ - React
Testing Recipes include many examples that you can copy and paste. ... function Box() { const [state, setState] = useState({ left: 0, top:...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found