React functional component does not handle event - reactjs

I have storybook components, that I use in my project. So I need to use Card component in my project, which needs to be added some styling. So I add style using "styled" from styled-component. After I export my new CardNew and try yo use it in some pages. It works, but when I try to add onMouseLeave/onMouseEnter events to that component, it does not work.
When I try to use Card's initial version from storybook, without any styling and add event, it works.
Here is my code.
const CardStyled = styled(Card)`
width: 200px;
height: 100px;
margin-bottom:10px;
color:red;
line-height: 1.5em;
`;
export default function CardNew(props) {
return (
<CardStyled>
<Card.Body>
<p>{props.content}</p>
</Card.Body>
</CardStyled`enter code here`>
)
}
And then I use that component and try to handle any event
<CardNew onMouseEnter={() => onMouseEnter()} onMouseLeave={() => onMouseLeave()} >
</CardNew>
Can anyone explain why I can't make styling on storybook component, then use it?
Thanks.

Because your CardNew component is not HTML component. So, you should pass all props donw. Like:
export default function CardNew(props) {
return (
<CardStyled>
<Card.Body>
<p {...props}>{props.content}</p>
</Card.Body>
</CardStyled`enter code here`>
)
}
This will allow you to handle any event to element.

Related

How to use styled-component CSS props with Typescript

I map over an array of colors, which is defined in the database. I want to pass this colors as background for the created divs. Like I am used to, the console shows me, that the colors out of the array are passed in as prop. But using the props in styled components not works in typescript. I tried the following, what I have found in the net:
import * as types from 'styled-components/cssprop'
import type {} from 'styled-components/cssprop';
/// <reference types="styled-components/cssprop" />
I only passed this variations into my file.
The both snippets:
<ColorHolder>
{item.colors.map((color)=>(
<div color={color}></div>
))}
</ColorHolder>
css:
& div{
width:20px;
height:20px;
border-radius:50%;
background:${props=>props.color};
}
As far as I understand your code, you don't need to use any libraries.
Here is the working example, where colors in the array you fetched from backend
<div>
{
colors.map(color=>(
<div style={{backgroundColor: color, height: "50px",width: "50px"}}>
.
</div>))
}
</div>
Here's full example - codesandbox.io
Only styled components can receive props for this style adaptation technique.
Therefore in your case simply create a quick styled div:
const StyledDiv = styled.div<{ color: string }>`
background: ${props => props.color};
`;
<ColorHolder>
{item.colors.map((color) => (
<StyledDiv color={color}></StyledDiv>
))}
</ColorHolder>

Is it possible to use the touch ripple effect of MUI on a div?

I have read different answers of similar questions, but they are all old and don't seem to work in the latest version of MUI.
I need to apply the touch ripple effect on a div, but I can't use a button or a ButtonBase element because there is another button inside it.
Thanks in advance for the reply.
Yes, you can use TouchRipple to emulate the ripple effect. This component is undocumented, but you can see how it's used in the ButtonBase and learn to use it yourself.
First, you need to pass a ref to TouchRipple and call ref.current.start(e) or ref.current.stop(e) when you want to start or stop the effect respectively.
e is the event object. When you call start(e), it needs the mouse or touch position (from mousedown or touchstart event) to know where to start the ripple effect (Source). You can override this behavior by setting center props to true, which makes the ripple effect always start at the middle.
Below is the minimum working example to get you started:
function App() {
const rippleRef = React.useRef(null);
const onRippleStart = (e) => {
rippleRef.current.start(e);
};
const onRippleStop = (e) => {
rippleRef.current.stop(e);
};
return (
<div
onMouseDown={onRippleStart}
onMouseUp={onRippleStop}
style={{
display: "inline-block",
padding: 8,
position: "relative",
border: "black solid 1px"
}}
>
Button
<TouchRipple ref={rippleRef} center={false} />
</div>
);
}
Live Demo
You Can Use ButtonBase API
With ButtonBase API you can pass component prop as div or any component you want
For Eg.
import { ButtonBase, Typography } from "#mui/material";
const App = () => {
return (
<ButtonBase component="div">
<Typography fontSize="1.2rem">Hello, I'm a div with MUI Ripple Effect!</Typography>
</ButtonBase>
)
}
export default App;

Getting simple styles to work with react arrow functions

I appreciate this may be a little basic here, but I'm relatively new to React and am testing the waters with various ways of applying on-the-fly styling rather than creating separate stylesheets and importing them.
I'm trying to experiment adding styles to three different elements - one via inline styles, another via a style tag, and another via a style variable - where only the inline style seems to work.
Here is my code with all 3 elements:
import React from 'react'
const App = () => {
render {
const testOneStyle = {
color: "red",
fontWeight: "bold"
};
return (
<div>
<span style={testOneStyle} className="test-one">test 1</span>
<span className="test-two">test 2</span>
<style>
.test-two {
color: red;
font-weight: bold
}
</style>
<span style={{color: "red"}} className="test-three">test 3</span>
</div>
)
}
}
export default App
Firstly, does the variable style (i.e. here) only work with class components rather than functional components?
And can someone explain why this is not rendering and how to render and apply the styles?
Thank you for any advice. Here is a StackBlitz demo: https://stackblitz.com/edit/react-tjukup
Unfortunately, <style> tags don't work in JSX the way they do in html. You are going to have to parse the the string appropriately yourself, since JSX is just javascript with syntactical sugar to convert into React.createElement() function with the right parameters. So you want to generally avoid style and head tags in JSX, but if you do, you want to use it like:
<style>
{"\
.test-two {\
color: red;\
font-weight: bold;\
}\
"}
</style>
EDIT
Also, to answer your question "does the variable style only work with class components rather than functional components?", no. The prop style is a JSX prop and works regardless of what kind of component you are using.
EDIT
And the reason why your component is not rendering, is because render() is a function that is only used in class based components. In a functional component you just directly return the JSX.
import React from "react";
const App = () => {
const testOneStyle = {
color: "red",
fontWeight: "bold"
};
return (
<div>
<span style={testOneStyle} className="test-one">
test 1 - fails
</span>
<span className="test-two">test 2 - fails</span>
<style>
{`
.test-two {
color: red;
font-weight: bold
}
`}
</style>
<span style={{ color: "red" }} className="test-three">
test 3 - works
</span>
</div>
);
};
export default App;
EDIT
As you may have observed in the snippet I have provided, you can also use strings with "`" to make it easier to enter strings in JSX
I hope this may helps you
import React from 'react'
const App = () => {
const testOneStyle = {
color: "blue",
fontWeight: "bold"
};
return (
<div>
<span style={testOneStyle} className="test-one">
test 1 - fails
</span>
<span className="test-two">
test 2 - fails
</span>
<style>
{
`.test-two {
color: green;
font-weight: bold
}`
}
</style>
<span style={{color: "red"}} className="test-three">
test 3 - works
</span>
</div>
)
}
export default App
Explaination:
You are using functional component
Class component require render method to return a JSX. Functional component can directly return JSX.
you can add style tag in your JSX but the context inside need to be string.

React-testing-library not rendering computed styles from stylesheet

Basic scenario is such: I have a component which has width: 100% as defined in a stylesheet. Therefore it should retain the width of its parent component. I want to calculate the width of my component and apply it to my child component because I am rendering it via createPortal and I would like them to be the same width. This works in the browser. However, in my test, I am finding that window.getComputedStyle(component) is not returning any of the styles applied from the stylesheet.
As suggested, I could mock the javascript window, but that's actually counter to what I'm hoping to do, I think. I want to verify the behavior that is present in the browser, that window.getComputedStyle() returns all styles applied, not just the inline styles.
I have put a simple example into a codesandbox: https://codesandbox.io/s/goofy-wilson-6v4dp
Also here:
function App() {
return (
<div className="App">
<WidthComponent />
</div>
)
}
function WidthComponent() {
const myInput = useRef();
const [inputWidth, setInputWidth] = useState(0);
useEffect(() => {
console.log("in handleLoad");
const width = myInput.current ? myInput.current.offsetWidth : 0;
setInputWidth(width);
}, [myInput]);
return (
<div className="inherited-width" ref={myInput}>
<div style={{ width: inputWidth }} className="child-element">
Hello
</div>
</div>
);
}
// test
test("width is inherited", () => {
const { rerender } = render(
<div style={{ width: "452px" }}>
<WidthComponent />
</div>
);
const element = document.getElementsByClassName("child-element").item(0);
rerender(
<div style={{ width: "452px" }}>
<WidthComponent />
</div>
);
expect(window.getComputedStyle(element).width).toBe("452px");
});
.App {
font-family: sans-serif;
text-align: center;
width: 500px;
}
.inherited-width {
width: inherit;
}
Any help is appreciated.
However, in my test, I am finding that window.getComputedStyle(component) is not returning any of the styles applied from the stylesheet.
Note that if you're running your tests in JSDOM (i.e. every Jest test) then CSS isn't fully implemented. Specifically, the cascade part of CSS is not implemented (https://github.com/jsdom/jsdom/pull/2690). Inheritance is only partially implemented (display and visibility) (https://github.com/jsdom/jsdom/issues/2160).
I would suggest running tests that assert on computed styles only in browsers, not JSDOM. A codesandbox test is not running in an actual browser environment.

Dropdown menu flip position issue. React-Select + Material-UI Popper

I use the example autocomplete field from the Material-UI lib documentation. (https://material-ui.com/demos/autocomplete/#react-select)
There is a problem with fliping the menu when it opens at the bottom of the page or the browser's viewport.
Is there a way to fix this problem with Material-UI and react-select?
Or do I need to write something custom?
If you are not using a <Menu/> custom component, you can use the menuPlacement="auto" prop of <Select/>, then your problem is solved.
const components = {
Control,
// Menu , <-- delete it
NoOptionsMessage,
Option,
Placeholder,
SingleValue,
ValueContainer
};
https://github.com/JedWatson/react-select/issues/403
Otherwise you can choose another selector, material-ui provides 2 more differents integration with the <Popper/> component: react-autosuggest and downshift.
https://material-ui.com/demos/autocomplete/
Hope it helps!
i've faced the same problem, for <Select /> component i have used what TomLgls suggest, but for <AsyncSelect /> as a work-around, i used some offset calculations in my component :
const rootHeight = document.getElementById('root').offsetHeight ;
const selectElement = document.getElementById('async_select_container_id');
const selectOffsetBottom= selectElement.offsetHeight + selectElement.offsetTop;
...
<AsyncSelect
{...listProps}
menuPlacement={
rootHeight - selectOffsetBottom > 210 ? 'auto' : 'top' // react-select menu height is 200px in my case
}
/>
i hope it helps as well
If you have created customMenu component then in that give className as open-menu-top and write this code for class:
.menu-open-top {
top: auto;
bottom: 100%;
}
Your CustomMenu maybe look like this:
const CustomMenu = ({ children, innerProps, innerRef, selectProps }) => {
return (
<div
ref={innerRef}
{...innerProps}
className={`rs-menu ${customMenuClass} open-menu-top`}
>
{Your Logic}
</div>
);
};

Resources