I'm using react-virtuoso with material ui, I'm trying to hover on specific row and add action when hover.
example of the code:
https://codesandbox.io/s/hqt3js
I tried to add <TableRow> in rowContent function render
function rowContent(_index: number, row: Data) {
return (
<React.Fragment>
<TableRow
hover={true}
onMouseEnter={() => {
console.log('hover');
}}
>
{columns.map((column) => (
<TableCell key={column.dataKey} align={column.numeric || false ? 'right' : 'left'}>
{row[column.dataKey]}
</TableCell>
))}
</TableRow>
</React.Fragment>
);
}
I'm getting the error:
Warning: validateDOMNesting(...): <tr> cannot appear as a child of <tr>.
Related
Im doing a unit test for my component. It consists of 6 <input> elements, where the first input is set to be auto focused. I am trying to test this.
Here is my test code:
import React from 'react';
import { configure, shallow, ShallowWrapper } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import HCPinCode from './HCPinCode';
configure({ adapter: new Adapter() });
describe('<HCPinCode>', () => {
let wrapper: ShallowWrapper;
beforeEach(() => {
wrapper = shallow(
<HCPinCode
length={6}
hasFailed={false}
codeChangeHandler={(_: string) => {}}
></HCPinCode>
);
});
it('mounts without crashing', () => {
wrapper.unmount();
});
it('should be rendered and first input element should be auto-focused', () => {
const inputElement = wrapper.find('input:first-child').getElement();
expect(document.activeElement).toBe(inputElement);
});
});
When I run the unit test I get failure:
● <HCPinCode> › should be rendered and first input element should be auto-focused
expect(received).toBe(expected) // Object.is equality
- Expected - 7
+ Received + 1
- <input
- autoFocus={true}
- className="field"
- onKeyDown={[Function onKeyDown]}
- onPaste={[Function onPaste]}
- value=""
- />
+ <body />
basically it recognized the focused one as the body.
This is the component itself:
return (
<div className={containerClasses} ref={containerRef}>
{codeState.map((codeValue, index) => (
<input
key={index}
autoFocus={index === 0}
className={fieldClasses}
value={codeValue}
onKeyDown={({ key }) => onKeyDown(key, index)}
onPaste={(e) => onPaste(e, index)}
/>
))}
</div>
codeState is just an array of numbers.
Also I console log the HTML tree built:
it('should be rendered and first input element should be auto-focused', () => {
const inputElement = wrapper.find('input:first-child').getElement();
console.log(wrapper.html());
expect(document.activeElement).toBe(inputElement);
});
The log I get in console:
<div class="container"><input autofocus="" class="field" value=""/><input class="field" value=""/><input class="field" value=""/><input class="field" value=""/><input class="field" value=""/><input class="field" value=""/></div>
Indeed my first element has autofocus attribute.
I want to add conditional CSS property to a div in such a way that if particular condition is true then only it will applied. Below is my code.
const Select = ({
handleClick,
title,
permission,
}: SelectProps) => {
return (
<div
onClick={handleClick}
style={{
marginTop: '16px',
cursor: 'pointer',
pointerEvents <-- make this property conditional
${({ permission }) => permission && `pointerEvents: none;`} <-- tried this but not working
}}
>
<Title>{title}</Title>
</div>
);
};
export const RenderSelectBlock = () => {
const checkUserPermission = checkUserPermission();
return (
<Select
handleClick={() => setSelectType('Google')}
title="Google"
checkUserPermission={checkUserPermission}
/>
<Select
handleClick={() => setSelectType('Microsoft')}
title="Microsoft"
checkUserPermission={checkUserPermission}
/>
<Select
handleClick={() => setSelectType('Apple')}
title="Apple"
checkUserPermission={checkUserPermission}
/>
<Select
handleClick={() => setSelectType('Facebook')}
title="Facebook"
checkUserPermission={checkUserPermission}
/>
)
);
};
So here in the last Select where title is Facebook, I want to disable it if the user don't have permission i.e. permission = false. Basically pointerEvents property should only be added for title= Facebook and should be set to none if permission = false.
You best option is to avoid style entirely and use className, then include a second class (maybe no-pointer-events) for the pointer-events you want to optionally include:
<div
className={`main-class ${permission ? "no-pointer-events" : ""}`}
But if you want to do it with style, you could use undefined for when you don't want to specify it:
<div
style={{
marginTop: '16px',
cursor: 'pointer',
pointerEvents: permission ? "none" : undefined,
}}
You could also define the style object before reaching this point in the code:
const style = {
marginTop: '16px',
cursor: 'pointer',
};
if (permission) {
style.pointerEvents = "none";
}
Then use it:
<div
style={style}
Sometimes you'll see people do this with multiple properties via spread syntax:
<div
style={{
marginTop: '16px',
cursor: 'pointer',
...(permission ? {pointerEvents: "none"} : undefined),
}}
...undefined is fine in an object literal (it doesn't add any properties).
While working with the controlled input components if we set the value of the controlled component to null or undefined the previous value is still displayed on the UI instead of changing it and the state holding that input value changes to null or undefined. I have created a sandbox for better understanding
https://codesandbox.io/s/black-architecture-0wqw1
Thank you
If the data type is null or undefined react automatically supress that value and log nothing.
If you want to see the type of that particular value, write {typeof data}, then you'll get your answer.
...
setData(null)
typeof data // object
setData("hi")
typeof data // string
setData(undefined)
typeof data // undefined
...
here is quick fix, it never changes value variable, if data then put data else empty string, that how it works
<input
type="text"
onChange={(e) => setData(e.target.value)}
value={data ? data:""}
/>
i hope this will solve your problem,
here is complete fix,
https://codesandbox.io/embed/optimistic-currying-snn8t?fontsize=14&hidenavigation=1&theme=dark
You can use ref tout change the value of your input anywhere outside your input component, see bellow :
import React, { useState, useEffect } from "react";
import "./styles.css";
export default function App() {
const [data, setData] = useState(null);
const inputRef = React.useRef(null);
useEffect(() => {
console.log(data);
}, [data]);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<input
ref={inputRef}
type="text"
onChange={(e) => setData(e.target.value)}
value={data}
/>
<div style={{ marginTop: "10px" }}>
<button onClick={() => {
setData(null);
inputRef.current.value = ''
}}>SET DATA NULL</button>
</div>
<div style={{ marginTop: "10px" }}>
<button onClick={() => {
setData(undefined)
inputRef.current.value = ''
}}>
SET DATA UNDEFINED
</button>
</div>
<div style={{ marginTop: "10px" }}>INPUT VALUE {data}</div>
</div>
);
}
I have a ReactMapGL component in my page that is stored above the footer and below the navbar. In my initial screen from my desktop the layout looks fine, but when I inspect element to make the screen size smaller, the layout becomes unresponsive.
So far this is my code for this particular page:
export default function Map({posts}) {
const [viewport, setViewport] = useState({
latitude: 45.4211,
longitude: -75.6938,
width:"100vw",
height:"100vh",
zoom: 10,
});
const [selectedProperty, setSelectedProperty] = useState(null)
return (
<div>
<ReactMapGL {...viewport} mapboxApiAccessToken="//mykey"
mapStyle="mapbox://styles/jay/cks5xkaa892cp17o5hyxcuu0z"
onViewportChange={viewport => {
setViewport(viewport);
}}>
{
posts &&
posts.map((maps) => (
<Marker key={maps.id} latitude={maps.Latitude} longitude={maps.Longitude}>
<button className="marker-btn" onClick={e => {
e.preventDefault();
setSelectedProperty(maps);
}}>
<img src="placeholder.svg"/>
</button>
</Marker>
))}
{selectedProperty ? (
<Popup latitude={selectedProperty.Latitude} longitude={selectedProperty.Longitude}
onClose={() => {setSelectedProperty(null);}}>
<h1>{selectedProperty.Title}</h1>
</Popup>) : null}
</ReactMapGL>
</div>
);
}
For the Navbar and footer I have copy pasted the html and css from here.
I have written this react component where I want the list element to be traversable thorough the key up and down buttons. I am able to do using tab-index with tab and shift tab, but instead I want to use key up and down.
export const NotificationListComponent: React.FunctionComponent<INotifications> = (
props
) => {
return (
<>
{props.notifications &&
props.notifications.map((item) => {
return (
<li
key={item.notificationId}
style={NotificationListStyle}
role="listitem"
tabIndex={0}
>
<NotificationItemComponent {...item} />
</li>
);
})}
</>
);
};```