React JS create dynamic element on json loop - javascript

I am using react JS to build a form creator. Right now I'm focused on the process of rendering the element inside the form, basically it's a div containing some other divs, as a child.
I have my main component (Form) and some child that can be different components, like textbox or dropdown, and so on, with a set of common properties, and a set of specific properties (for instance the dropdown options are not inserted in the textbox component).
I'm also fetching the data from an API that respond with a json with a "type" parameter ("textbox", "dropdown", etc).
I'm looping on the json, and for sure I can just check the type and IF it's textbox create a textbox, IF it's a dropdown create a dropdown... But i think there is a better solution.
This is my code:
import {useState, useEffect} from 'react';
import axios from 'axios';
import Textbox from './Textbox';
import Dropdown from './Dropdown';
function Form(){
const [loading, setLoading] = useState(true);
const [components, setComponents] = useState([]);
useEffect(() => {
if(loading){
fetchComponents()
}
});
const fetchComponents = () => {
axios({
method: 'get',
url: 'http://localhost:8000/api/position'
})
.then(res => {
setComponents(res.data);
setLoading(false);
});
}
const allItems = () => {
return(
components.map((component, key) => {
/** THIS IS WHERE I WANT TO CREATE THE ELEMENT DYNAMICALLY */
const options = JSON.parse(component.options);
if(component.type === 'textbox'){
return <Textbox
key={component.id}
id={ component.id}
name={component.name}
default={{
x: options.position.x,
y: options.position.y,
width: options.size.width,
height: options.size.height
}}
minWidth={100}
minHeight={100}
resizeGrid={[20, 20]}
dragGrid={[20, 20]}
label={component.label}
value={component.value}
bounds="window"
/>
}
if(component.type === 'dropdown'){
return <Dropdown
key={component.id}
id={ component.id}
name={component.name}
default={{
x: options.position.x,
y: options.position.y,
width: options.size.width,
height: options.size.height
}}
minWidth={100}
minHeight={100}
resizeGrid={[20, 20]}
dragGrid={[20, 20]}
label={component.label}
value={component.value}
dropdown_options={component.dropdown_options}
bounds="window"
/>
}
})
)
}
return(
<div>
<div className="box background-quaderno" style={{height: '500px', width: '500px', position: 'relative', overflow: 'auto', padding: '0'}}>
<div style={{height: '100%', width: '100%', padding: '0px', overflow: 'hidden'}}>
{loading ? <></> : allItems()}
</div>
</div>
</div>
)
}
export default Form;
Thanks!

Related

ToolTip does not disappear on scroll

I have a button on the site and a ToolTip to it, which describes the action of the button.
But there is one bug that I can not solve (and I'm already starting to doubt if there is a solution to this problem).
Description of the problem: when the user hovers over the icon, a tooltip appears - everything works fine here. But if at this moment the table is scrolling, then the tooltip flies out of bounds. It's hard to describe, take a look
Pay attention to how the tooltip (if the cursor is hovered over) flies up or down when scrolling.
Tell me how to solve this problem?
<div>
<Tooltip
title="Delete"
arrow
componentsProps={{
tooltip: {
sx: {
bgcolor: '#a3a3a3',
'& .MuiTooltip-arrow': {
color: '#a3a3a3',
},
},
},
}}
PopperProps={{
modifiers: [
{
name: "offset",
options: {
offset: [0, -8],
},
},
],
}}>
<DeleteForeverIcon/>
</Tooltip>
</div>
Instruction: hover over any cell from the first column, wait for the tooltip to appear. Then scroll the wheel up or down and see how the tooltip goes outside the table
P.s. Please note that this question has already been answered. And in principle this solution is working. But I had a lot of problems when adding this solution to my real code. Probably a simple solution for me here would be to simply cancel the scrolling when you hover over the button. Tell me how this can be done (but keep in mind that position: fixed is not suitable in this case)
My approach is different, where each tooltip maintains its own state. It is using IntersectionObserver to determine if the ToolTip component is viewable. When the component is no longer viewable, it will hide the Popper (the tooltip popup) by setting the CSS to display: 'none' via the sx prop on PopperProps.
Codesandbox Example: Here
Here is the modified file FileDownloadButton.jsx:
import React from "react";
import FileDownloadIcon from "#mui/icons-material/FileDownload";
import { ButtonGroup, Tooltip } from "#mui/material";
export default function FileDownloadButton() {
const tipRef = React.useRef(null);
const [inView, setInView] = React.useState(false);
const cb = (entries) => {
const [entry] = entries;
entry.isIntersecting ? setInView(true) : setInView(false);
};
React.useEffect(() => {
const options = {
root: null,
rootMargin: "0px"
};
const ref = tipRef.current;
const observer = new IntersectionObserver(cb, options);
if (ref) observer.observe(ref);
return () => {
if (ref) observer.unobserve(ref);
};
}, [tipRef]);
return (
<ButtonGroup>
<div>
<Tooltip
ref={tipRef}
title="Download record "
arrow
componentsProps={{
tooltip: {
sx: {
bgcolor: "#a3a3a3",
"& .MuiTooltip-arrow": {
color: "#a3a3a3"
}
}
}
}}
PopperProps={{
sx: { display: inView ? "block" : "none" },
modifiers: [
{
name: "offset",
options: {
offset: [0, -8]
}
}
]
}}
>
<FileDownloadIcon />
</Tooltip>
</div>
</ButtonGroup>
);
}
Changes for reference
Change 1
export default function FileDownloadButton() {
const tipRef = React.useRef(null);
const [inView, setInView] = React.useState(false);
const cb = (entries) => {
const [entry] = entries;
entry.isIntersecting ? setInView(true) : setInView(false);
};
React.useEffect(() => {
const options = {
root: null,
rootMargin: "0px"
};
const ref = tipRef.current;
const observer = new IntersectionObserver(cb, options);
if (ref) observer.observe(ref);
return () => {
if (ref) observer.unobserve(ref);
};
}, [tipRef]);
Change 2
PopperProps={{
sx: { display: inView ? "block" : "none" },
Update 1
Original poster wants toggle
Codesandbox example
import React, { useState } from "react";
import FileDownloadIcon from "#mui/icons-material/FileDownload";
import { ButtonGroup, IconButton, Tooltip } from "#mui/material";
import VisibilityOffIcon from "#mui/icons-material/VisibilityOff";
import VisibilityIcon from "#mui/icons-material/Visibility";
export default function FileDownloadButton() {
const [click, setClick] = useState(true);
const tipRef = React.useRef(null);
const [inView, setInView] = React.useState(false);
const cb = (entries) => {
const [entry] = entries;
entry.isIntersecting ? setInView(true) : setInView(false);
};
React.useEffect(() => {
const options = {
root: null,
rootMargin: "0px"
};
const ref = tipRef.current;
const observer = new IntersectionObserver(cb, options);
if (ref) observer.observe(ref);
return () => {
if (ref) observer.unobserve(ref);
};
}, [tipRef]);
return (
<ButtonGroup>
<div>
<Tooltip
ref={tipRef}
title={click ? "Show item" : "Hide Item"}
arrow
componentsProps={{
tooltip: {
sx: {
bgcolor: "#a3a3a3",
"& .MuiTooltip-arrow": {
color: "#a3a3a3"
}
}
}
}}
PopperProps={{
sx: { display: inView ? "block" : "none" },
modifiers: [
{
name: "offset",
options: {
offset: [0, -8]
}
}
]
}}
>
<IconButton onClick={() => setClick(!click)}>
{click ? <VisibilityOffIcon /> : <VisibilityIcon />}
</IconButton>
</Tooltip>
</div>
</ButtonGroup>
);
}
I think this is browser specific issue. When I checked the given url( https://codesandbox.io/s/silly-grass-1lb3qw) in firefox browser it was working fine(but not in the chrome). Later figured that out hover while scrolling on element will work differently in the chrome compare to other browsers since latest versions.
I made following changes to make it work in chrome. Basically whenever we hover any item then the material tooltip is being added to the document. So what I did was I have attached an scroll event and if there is any material tooltip element is present I just simply removed it.
DeviceTable.jsx
export default function DevicesTable() {
const tableRef = useRef();
function removeElementsByClass(className){
const elements = document.getElementsByClassName(className);
while(elements.length > 0){
elements[0].remove();
}
}
useEffect(() => {
if (tableRef.current) {
tableRef.current.addEventListener("scroll", (e) => {
// CLASS NAME OF THE TOOLTIP ATTACHED TO THE DOM. THERE ARE MULTIPLE CLASSES BUT I FOUND FOLLOWING CLASSNAME TO BE UNIQUE. PLEASE CROSS CHECK FROM YOUR END AS WELL.
//YOU CAN CHECK THIS BY PASSING open={true} attribute on <Tooltip> AND INSPECT DOM
removeElementsByClass("css-yk351k-MuiTooltip-tooltip")
});
}
return () => {
if(tableRef.current) {
tableRef.current.removeEventListener("scroll", ()=>{});
}
}
}, []);
return (
<TableContainer className="TableContainerGridStyle">
<Table className="TableStyle">
<DevicesTableHeader />
// CHANGED LINE
<TableBody ref={tableRef} className="TableBodyStyle">
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
<DevicesTableCell />
</TableBody>
</Table>
</TableContainer>
);
}
Apart from the above I think you can use another alternatives like followCursor, setting the position relative attribute to the table cell(TableCellStyle) or body. But these don't solve the problem fully.
As you are passing Table component as props children to the StateLabel component so in order to display/render we need to update StateLabel component to use props.children
export default function StateLabel({children}) {
return <div>{children}</div>;
}
Div hover not working when scrolling in chrome

MUI DataGridPro crashes when reordering columns by drag&drop, when already using react-dnd in the parent component

My app is a dashboard of MUI <Card />s that can be dragged-and-dropped (d&d) to reorder them. The d&d logic is implemented using react-dnd and has been working well so far.
However, when I add a <DataGridPro /> as the child of a draggable <Card />, the datagrid's native Column ordering - which also is done by dragging-and-dropping - breaks. Dragging a column once or twice generates the following crash:
Invariant Violation
Cannot call hover while not dragging.
▼ 5 stack frames were expanded.
at invariant (https://bfz133.csb.app/node_modules/
react-dnd/invariant/dist/index.js:19:15
checkInvariants
https://bfz133.csb.app/node_modules/dnd-core/dist/actions/dragDrop/hover.js:33:40
DragDropManagerImpl.hover
https://bfz133.csb.app/node_modules/dnd-core/dist/actions/dragDrop/hover.js:18:5
Object.eval [as hover]
https://bfz133.csb.app/node_modules/dnd-core/dist/classes/DragDropManagerImpl.js:25:38
HTML5BackendImpl.handleTopDrop
https://bfz133.csb.app/node_modules/react-dnd-html5-backend/dist/HTML5BackendImpl.js:455:20
▲ 5 stack frames were expanded.
This screen is visible only in development. It will not appear if the app crashes in production.
Open your browser’s developer console to further inspect this error.
This error overlay is powered by `react-error-overlay` used in `create-react-app`.
You can begin dragging, the crash only happens when you let go of the mouse button.
The expected behavior is that I should be able to d&d the columns, to change their order, without issues.
Things I've tried
Removing the <DataGridPro /> and replacing that <Card /> with a text-type Card (see the code in the sandbox below) shows that d&d logic works fine with no crashes;
Disabling my app's d&d by commenting out all the relevant code causes the <DataGridPro />'s colum reordering to work as expected;
The above suggests the root cause lies in having both D&Ds work without causing an internal conflict in react-dnd, which led to me trying:
Browsing the documentation to find a way to instruct the component to use my own DndProvider or DndManager, but I couldn't find that in the API - sorry if I misread it!
Googling for the error message "Cannot call hover while not dragging", while limiting myself to contexts including the MUI library or react-dnd, yielded limited results. I found a Chrome bug that was fixed on v. 77.0.3865.120, my Chrome version is 101.0.4951.64 .
EDIT: Found this bug, but it's closed. Should I open a new one? I'd like some input on this, as I wouldn't like to bother the developers if the problem is in my code.
Minimum verified reproducible example
I made a sandbox! Click here to see it
Datagrid Component:
import React from "react";
import { DataGridPro } from "#mui/x-data-grid-pro";
import { useDemoData } from "#mui/x-data-grid-generator";
export function MyDatagridPro() {
const { data } = useDemoData({
dataSet: "Commodity",
rowLength: 5,
maxColumns: 6
});
return <DataGridPro {...data} />;
}
Card widget:
import React, { useRef } from "react";
import {
Card,
CardHeader,
CardContent,
Grid,
Typography,
Divider
} from "#mui/material";
import { useDrag, useDrop } from "react-dnd";
import { MyDatagridPro } from "./MyDatagridPro";
export function MyContentCard(props) {
const domRef = useRef(null);
const [{ isDragging }, dragBinder, previewBinder] = useDrag(
() => ({
type: "mycard",
item: () => ({
orderIndex: props.orderIndex
}),
collect: (monitor) => ({
isDragging: monitor.isDragging()
})
}),
[props]
);
const [{ handlerId, isOver }, dropBinder] = useDrop(
() => ({
accept: "mycard",
collect: (monitor) => ({
handlerId: monitor.getHandlerId(),
isOver: !!monitor.isOver()
}),
canDrop: (item, monitor) => {
if (!domRef.current) return false;
const draggingOrderIndex = item.orderIndex;
const hoveringOrderIndex = props.orderIndex;
if (draggingOrderIndex === hoveringOrderIndex) return false;
const hoverRectangleBound = domRef.current?.getBoundingClientRect();
const [hoverItemX, hoverItemY] = [
hoverRectangleBound.right - hoverRectangleBound.left,
hoverRectangleBound.bottom - hoverRectangleBound.top
];
const mousePosition = monitor.getClientOffset();
const [hoverMouseX, hoverMouseY] = [
mousePosition.x - hoverRectangleBound.left,
mousePosition.y - hoverRectangleBound.top
];
if (
(hoverMouseX < 0 || hoverMouseX > hoverItemX) &&
(hoverMouseY < 0 || hoverMouseY > hoverItemY)
) {
return false;
}
return true;
},
drop: (item) => {
props.swapper(item.orderIndex, props.orderIndex);
}
}),
[props]
);
return (
<Grid item xs={5}>
<Card
ref={(element) => {
if (element) {
domRef.current = element;
previewBinder(dropBinder(domRef));
}
}}
sx={{
height: `calc(6 * 4.5rem)`,
opacity: isDragging ? 0.3 : 1,
display: "flex",
flexDirection: "column",
border: isOver ? "2px solid rgba(0,0,0,0.5);" : ""
}}
data-handler-id={handlerId}
>
<CardHeader ref={dragBinder} title={props.title} />
<Divider />
<CardContent
sx={{
height: "100%",
display: "flex",
flexDirection: "column"
}}
>
{props.type === "text" && <Typography>{props.content}</Typography>}
{props.type === "datagrid" && <MyDatagridPro />}
</CardContent>
</Card>
</Grid>
);
}
export default MyContentCard;
App.js:
import React, { useState } from "react";
import { Grid } from "#mui/material";
import { createDragDropManager } from "dnd-core";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import { MyContentCard } from "./MyContentCard";
export const dndManager = createDragDropManager(HTML5Backend);
export default function App() {
const [cards, setCards] = useState([
{
type: "datagrid",
title: "Card 01 - A MUI DataGridPro",
content: ""
},
{
type: "text",
title: "Card 02 - Some text",
content: "Text that belongs to card 2"
}
]);
function swapCards(indexA, indexB) {
const newState = cards.slice();
const cardA = Object.assign({}, cards[indexA]);
newState[indexA] = Object.assign({}, cards[indexB]);
newState[indexB] = cardA;
setCards(newState);
}
return (
<DndProvider manager={dndManager}>
<Grid
container
spacing={1}
columns={10}
p={2}
pb={3}
mt={0}
mb={0}
// flex="1 1 auto"
overflow="auto"
sx={{
backgroundColor: "lightgray"
}}
>
{cards.map((card, i) => {
return (
<MyContentCard
key={i}
type={card.type}
title={card.title}
content={card.content}
orderIndex={i}
swapper={swapCards}
/>
);
})}
</Grid>
</DndProvider>
);
}

How to display an icon inside input field which got updated?

I have input boxes which are mapped with an object.
Looking for a solution if the input got updated or any user typed something in input field and then submit then that input field should display an icon inside it(for example if someone updated the first and last input field than only first and last field should contain the icon(Admin) other input boxes should be as it is.)
import React, { useState } from "react";
import Admin from 'icons'
//more imports
export default function InputCom() {
const [value, setValue] = useState("");
const data = [
{ label: "first", name: "first" },
{ label: "last", name: "last" },
{ label: "phone", name: "phone" },
];
const handleChange = (event) => {
setValue(event.target.value);
};
const handleClick = () => {
console.log(vlaue)
}
return (
<div >
<Card >
<div >
{data.map((item, key) => (
<div key={key.name} >
<input
//icon={Admin}
label={item.name}
name={item.name}
onChange={handleChange}
placeholder="text"
value={value}
/>
</div>
))}
</div>
</Card>
<button onClick={handleClick}>submit<button>
</div>
);
}
You can create a component called InputWithIcon that extends a normal <input> tag but also adds the icon. And then pass the optional icon prop so that it only renders the icon when it's provided:
<InputWithIcon
icon={!!this.state.value && Admin}
...
/>
Place the icon on the right side of the input and adjust the styles so that it looks as if the icon is inside the input.
This is the pseudo code:
const InputWithIcon = ({ icon, ...props }) => {
return (
<div>
<input {...props} />
{icon && <img src={icon} />}
</div>
);
};
Styles:
div {
position: relative;
}
img {
position: absolute;
right: 10;
top: 10;
}
input {
padding: 10;
padding-right: 20;
}
Hope this gives you the idea.

another case when the state of a component changes but seems that the component does not

I have a react component that has a state variable:
showEditor
when showEditor is false it is supposed to show only a div with some number inside it (initially showEditor is false). If this state variable is true my react component is supposed to show a textbox and a button with "save" label inside another div -making dissapear the first div with the number-. This textbox will be used to change the number. For the first div (the one that only shows a number) I defined:
<div onClick={this.showEditorProc}>
{ this.state.showEditor ?
<div ....>
{ just the numeric value }
</div>
:
<div ....>
textBox
<button onClick={save and make show Editor false}>
Save
</button>
</div>
</div>
the function this.showEditorProc will modify the state of the showEditor variable to true and the save button and textbox components will appear (inside another div too). I created a function that will executed if the save button is clicked. This function modifies the showEditor variable to false however, I can not see the div with just the numeric value. Instead I still see the textbox with the save button. Is there something else I could be missing? Here it is the code of my component:
import React from 'react';
import ReactDOM from 'react-dom';
import NumberFormat from 'react-number-format';
export class NumericBox extends React.Component {
constructor() {
super();
this.state = {
enteredValue: '',
showNumEditor: false,
index: ''
};
this.showNumericEditor = this.showNumericEditor.bind(this);
this.handle_enteredValue_change = this.handle_enteredValue_change.bind(this);
this.saveCellInfo = this.saveCellInfo.bind(this);
this.loadBasicInformation = this.loadBasicInformation.bind(this);
}
saveCellInfo(e){
alert(this.state.index);
/* cellAuxParams = new Map([['updateCellValue', this.state.updateCellValue]]); */
console.log('numericBox.js>saveCellInfo>cellAuxParams= ------------------------------------------------ ' + 28);
console.log(this.props.cellAuxParams);
var f = this.props.cellAuxParams.get('updateCellValue');
this.setState({showNumEditor: false}, () => f(this.state.Index, '77'));
}
handle_enteredValue_change(values) {
const {formattedValue, value} = values;
// formattedValue = $2,223
// value ie, 2223
this.setState({enteredValue: value});
}
showNumericEditor()
{
this.setState({showNumEditor: true})
}
loadBasicInformation()
{
this.setState({enteredValue: this.props.enteredValue,
index: this.props.index
});
}
componentDidMount(){
this.loadBasicInformation();
}
componentWillReceiveProps(nextProps){
alert(nextProps.enteredValue);
this.setState({enteredValue: nextProps.enteredValue}, () => this.loadBasicInformation());
}
render() {
const table4controls = {
display: 'table',
width: this.props.style.width,
backgroundColor: 'white',
border: '0px solid #666666',
borderSpacing: '0px',
paddingBottom: '0em',
paddingTop: '0em'
};
const table4controls_RowStyle = {
display: 'table-row',
width: 'auto',
clear: 'both',
borderBottom: '5px'
};
const table4controls_ColsStyleA = {
float: 'left',
display: 'table-column',
width: '60px',
backgroundColor: 'white'
};
const table4controls_ColsStyleB = {
float: 'left',
display: 'table-column',
width: '20px',
backgroundColor: 'white'
};
const table4controls_ColsStyleC = {
float: 'left',
display: 'table-column',
width: '20px',
backgroundColor: 'white'
};
const btnStyle={
};
return (
<div onClick={this.showNumericEditor}>
{ this.state.showNumEditor ?
<div style ={table4controls}>
<div style={table4controls_RowStyle}>
<div style={table4controls_ColsStyleA}>
<NumberFormat style={{width: '60px'}}
value={this.state.enteredValue}
thousandSeparator={true}
prefix={this.props.prefix}
onValueChange={this.handle_enteredValue_change}
/>
</div>
<div style={table4controls_ColsStyleB}>
<button style={btnStyle} onClick={() => this.saveCellInfo(this.state.index)}>
▲
</button>
<button style={btnStyle} onClick={() => this.saveCellInfo(this.state.index)}>
▼
</button>
</div>
<div style={table4controls_ColsStyleC}>
<button style={btnStyle} onClick={(e) => {this.saveCellInfo(e, this.state.index)}}>
Save
</button>
</div>
</div>
</div>
:
<div syle={table4controls_ColsStyleA}>
{this.state.enteredValue}
</div>
}
</div>
);
}
}
You have an onClick={this.showNumericEditor} handler on the surrounding div, so when you press the save button, the click event bubbles up and invokes a this.setState({showNumEditor: true}).
To fix it, you can either restructure the rendering or call e.stopPropagation(); at the start of saveCellInfo. Also note that some of your this.saveCellInfo calls are not passing the event.

Dynamic components: Calling element by ref

One part of my application is an image gallery. When the user clicks on an image, I want to put an opaque layer over the image to visualize that it is selected.
When I display the layer, and I click on the image to deselect it, naturally I'm actually clicking on the layer.
Here's the relevant ReactJS code to show what I mean:
{images.map((i, idx) => (
<div key={"cont"+idx} className="container">
<img src={i.images} ref={"img"+idx} />
<div onClick={this.handleIconDeselect} id={"div_"+idx}></div>
</div>
)
)}
I tried to give the img a unique ref (as shown above), but I'm having trouble selecting the correct img.
This is how I try to select the correct image:
handleIconDeselect = (event) => {
var imgref = "icon"+event.target.id.split("_").pop();
this.refs.imgref.click();
}
However, I get the following error message:
TypeError: Cannot read property 'click' of undefined
How can I select the correct image while using unique refs?
Alternatively, if the way I'm trying to achieve this is bad practice (I know you should only use refs when absolutely necessary), what is a better way to do it?
Try use state as here: https://codesandbox.io/s/m4276x643y
Maybe that is not the best way but it give you an rough idea.
import React, { Component } from "react";
import { render } from "react-dom";
import Hello from "./Hello";
const coverStyle = {
position: "fixed",
top: 0,
left: 0,
zIndex: -1,
opacity: 0,
width: "100%",
height: "100%",
background: "#000"
};
const coverStyleShow = {
...coverStyle,
zIndex: 1,
opacity: 1
};
const imgShow = {
zIndex: 10,
position: "relative"
};
const images = [
"https://dummyimage.com/100.png/f10/fff",
"https://dummyimage.com/100.png/f20/fff",
"https://dummyimage.com/100.png/f30/fff",
"https://dummyimage.com/100.png/f40/fff",
"https://dummyimage.com/100.png/f50/fff",
"https://dummyimage.com/100.png/f60/fff",
"https://dummyimage.com/100.png/f70/fff"
];
class App extends Component {
constructor(props) {
super(props);
this.state = {
cover: coverStyle,
img: imgShow,
imgId: null,
imgShow: false
};
}
handleImageClick = (target, idx) => {
// you can do something with this "target"...
this.setState({
cover: coverStyle,
coverShow: coverStyleShow,
imgId: idx,
imgShow: !this.state.imgShow
});
};
render() {
return (
<div>
<Hello name="CodeSandbox" />
<h2>Start editing to see some magic happen {"\u2728"}</h2>
<div>
{images.map((img, idx) => (
<img
key={img}
src={img}
style={idx === this.state.imgId ? this.state.img : null}
onClick={event => this.handleImageClick(event.target, idx)}
alt="dummy img"
/>
))}
</div>
<span
style={this.state.imgShow ? this.state.coverShow : this.state.cover}
/>
</div>
);
}
}
render(<App />, document.getElementById("root"));

Categories

Resources