I want to make a simple memory game with react for a neat portfolio project. I have an array of 20 items and 10 sets of colors
const data = [
// Manchester Blue
{
ID: 1,
Color: "#1C2C5B"
},
{
ID: 2,
Color: "#1C2C5B"
},
// Seafoam Green
{
ID: 3,
Color: "#93E9BE."
},
{
ID: 4,
Color: "#93E9BE."
},
// Candy Apple Red
{
ID: 5,
Color: "#ff0800"
},
{
ID: 6,
Color: "#ff0800"
},
// Lake Placid Blue
{
ID: 7,
Color: "#3f5c9"
},
{
ID: 8,
Color: "#3f5c9"
},
// Safety Orange
{
ID: 9,
Color: "#ff6700"
},
{
ID: 10,
Color: "#ff6700"
},
// Vivid Orchard
{
ID: 11,
Color: "#cc00ff"
},
{
ID: 12,
Color: "#cc00ff"
},
// Apple Green
{
ID: 13,
Color: "#8db600"
},
{
ID: 14,
Color: "#8db600"
},
// Old Moss Green
{
ID: 15,
Color: "#867e36"
},
{
ID: 16,
Color: "#867e36"
},
// Canary Yellow
{
ID: 17,
Color: "#ffef00"
},
{
ID: 18,
Color: "#ffef00"
},
// Pink
{
ID: 19,
Color: "#ff1493"
},
{
ID: 20,
Color: "#ff1493"
}
];
I have the following basic HTML and CSS
HTML
<div>
<div className='flexbox-container'>
<div id='1' className='flexbox-item-one'></div>
<div id='2' className='flexbox-item-one'></div>
<div id='3' className='flexbox-item-one'></div>
<div id='4' className='flexbox-item-one'></div>
<div id='5' className='flexbox-item-one'></div>
</div>
<div className='flexbox-container'>
<div id='6' className='flexbox-item-two'></div>
<div id='7' className='flexbox-item-two'></div>
<div id='8' className='flexbox-item-two'></div>
<div id='9' className='flexbox-item-two'></div>
<div id='10' className='flexbox-item-two'></div>
</div>
<div className='flexbox-container'>
<div id='11' className='flexbox-item-three'></div>
<div id='12' className='flexbox-item-three'></div>
<div id='13' className='flexbox-item-three'></div>
<div id='14' className='flexbox-item-three'></div>
<div id='15' className='flexbox-item-three'></div>
</div>
<div className='flexbox-container'>
<div id='16' className='flexbox-item-four'></div>
<div id='17' className='flexbox-item-four'></div>
<div id='18' className='flexbox-item-four'></div>
<div id='19' className='flexbox-item-four'></div>
<div id='20' className='flexbox-item-four'></div>
</div>
</div>
CSS
.flexbox-item-one {
width: 100px;
height: 100px;
border: 3px solid black;
background-color: darkcyan;
margin: 1.5rem;
}
.flexbox-item-two {
width: 100px;
height: 100px;
border: 3px solid black;
background-color: greenyellow;
margin: 1.5rem;
}
.flexbox-item-three {
width: 100px;
height: 100px;
border: 3px solid black;
background-color: slateblue;
margin: 1.5rem;
}
.flexbox-item-four {
width: 100px;
height: 100px;
border: 3px solid black;
background-color: magenta;
margin: 1.5rem;
}
.flexbox-container {
display: flex;
justify-content: center;
}
I also have done some research and procured the following way to shuffle the array.
let shuffledColors = colors
.map(value => ({ value, sort: Math.random() }))
.sort((a, b) => a.sort - b.sort)
.map(({ value }) => value)
So my React skills are just not to the level where I can build this. I want to have an useEffect hook that loads the array when the project is rendered and uses the shuffle method. It would then have to dynamically add the colors to the HTML elements. SOmething which I'm not entirely sure how to do as well. Maybe an ForEach statement that uses the document.GetElementByID to add the css dynamically.
I would then have to get a way with positions to have two divs on top of each other which I can have the top one dynamically have its opacity altered on a onClick event to show the 'real colors'
Then there would have to be a check if the ID's of the colors match and a counter which keeps track of how many matches have been made.
For now I just want to get my head around how to have this array of colors randomised and assigned to the divs when loaded with the useEffect hook.
Ok, let's do it.
First, create a FlexboxContainer component that return a div with flexbox-container className:
const FlexboxContainer = ({ children }) => {
return <div className="flexbox-container">{children}</div>;
};
Next, create a FlexboxItem component, where the show/hide logic resides. Here, we don't need a stack of two divs. Instead, we use conditional backgroundColor styling that depends on actualColor state on a div. Here, we do have a onClick handler that would set the actualColor by using setActualColor setter once the user clicks the color card div. The show/hide (toggle) action would be based on the previous state of actualColor.
const FlexboxItem = ({ id, color, group }) => {
const [actualColor, setActualColor] = useState();
const handleClick = () => {
setActualColor((prevState) => (!prevState ? color : undefined));
};
return (
<div
id={id}
onClick={handleClick}
className={`flexbox-item-${group}`}
style={actualColor ? { backgroundColor: color } : null}
></div>
);
};
At the main component, we need to define currentColors state where we put our shuffledColors.
const [currentColors, setCurrentColors] = useState();
and we use useCallback hooks on shuffledColors
const shuffledColors = useCallback(() => {
return data
.map((value) => ({ value, sort: Math.random() }))
.sort((a, b) => a.sort - b.sort)
.map(({ value }) => value);
}, []);
since the shuffledColors going to be used inside a memoized groups constant where we re-structure the shuffledColors into groups of colors.
The aim of this grouping is to provide an array that is going to be used to render a dynamics group of five color divs by using the iteration of FlexboxContainer component.
const groups = useMemo(() => {
if (!currentColors) return [];
const chunkSize = 5;
const groupedItems = [];
for (let i = 0; i < currentColors.length; i += chunkSize) {
const chunk = currentColors.slice(i, i + chunkSize);
groupedItems.push(chunk);
}
return groupedItems;
}, [currentColors]);
...
return (
...
<div>
{currentColors &&
groups.map((items, index) => {
return (
<FlexboxContainer key={index}>
{items.map((item) => {
return (
<FlexboxItem
id={item.id}
color={item.color}
group={groupColors[index]}
key={item.id}
/>
);
})}
</FlexboxContainer>
);
})}
</div>
...
)
}
Next, we define a shuffleColors method, by which we can use it to set the initial colors inside a useEffect hook.
const shuffleColors = useCallback(() => {
const colors = shuffledColors();
setCurrentColors(colors);
}, [shuffledColors]);
useEffect(() => {
shuffleColors();
}, [shuffleColors]);
If we want to re-shuffle the colors, just call it from onCLick handler. Here we do a minor modification at FlexboxItem component and add a currentColor watcher.
const FlexboxItem = ({ id, color, group, show }) => {
const [actualColor, setActualColor] = useState();
// add show props change watcher
useEffect(() => {
setActualColor(show ? color : undefined);
}, [color, show]);
...
}
...
// current color watcher will reset showAll state on any currentColors state change
useEffect(() => {
setShowAll(false);
}, [currentColors]);
return (
...
<button onClick={shuffleColors}>Re-shuffle Colors</button>
...
)
It does not fully answer your question, at least, will give you new insight into how React works to achieve your objectives.
Here is the complete code of my explanation:
Related
What i want to accomplish is when i click on a box, the previous box to be behind the one that is on top, for better reference please check the next code.
https://codesandbox.io/s/optimistic-payne-4644yf?file=/src/styles.css
Desired behavior:
click on red box
click on blue box
and the sequence from bottom to top would be: green,red,blue
I tried a lot of ways but im keep messing up the code, so any help will be welcomed.
do you mean something like this?
const { useState, useEffect } = React
const Test = () => {
const [data, setData] = useState([
{ id: 1, label: "box 1", class: "box1", z: 0 },
{ id: 2, label: "box 2", class: "box2", z: 1 },
{ id: 3, label: "box 3", class: "box3", z: 2 }
]);
const handleClickBox = id => {
setData(p => {
let tmpArr = [...p];
tmpArr = tmpArr.sort((a) => a.id - (id + 1)).reverse().map((ta, i) => ({ ...ta, z: i })).sort((a, b) => a.id - b.id);
return tmpArr;
})
}
return <div className="box-wrapper">
{data.map((d, i) => {
return (
<div
className={d.class}
key={d.id}
style={{ left: i * 100, zIndex: d.z }}
onClick={() => handleClickBox(d.id)}
>
{d.label}
</div>
);
})}
</div>
}
ReactDOM.createRoot(
document.getElementById("root")
).render(
<Test />
);
.box-wrapper {
position: relative;
}
.box1,
.box2,
.box3 {
position: absolute;
width: 300px;
height: 150px;
color: white;
top: 0;
}
.box1 {
background: green;
}
.box2 {
background: red;
}
.box3 {
background: blue;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
When I was typing my response Layhout answered. That solution works, but mine is slightly different, you need to know the greatest value of zIndex.
import "./styles.css";
import { useState } from "react";
export default function App() {
const [data, setData] = useState([
{ id: 1, label: "box 1", class: "box1", index: 0 }, // red
{ id: 2, label: "box 2", class: "box2", index: 1 }, // blue
{ id: 3, label: "box 3", class: "box3", index: 2 } // green
]);
const handlePosition = (index, selectedIndex) =>
index === selectedIndex ? 2 : index > selectedIndex ? index - 1 : index;
const handleClick = (selectedIndex) => {
// nothing happens if we click on the first item
if (selectedIndex === 2) return;
setData(
data.map((i) => ({
...i,
index: handlePosition(i.index, selectedIndex)
}))
);
};
return (
<div className="App">
<div className="box-wrapper">
{data.map((b) => {
return (
<div
className={b.class}
key={b.id}
style={{ zIndex: b.index }}
onClick={() => handleClick(b.index)}
>
{b.label}
</div>
);
})}
</div>
</div>
);
}
Here is the full implementation on CodeSandbox.
The most important fact is zIndex of each object is also a UI state, so it needs to be in useState to change with user clicks. After this, you need to implement an algorithm to reorder items based on the clicked item. That is this function:
const handlePosition = (index, selectedIndex) =>
index === selectedIndex ? 2 : index > selectedIndex ? index - 1 : index;
It seems that the desired result may actually be a solution that handles z-index independently, without adding to the given data, and is capable of handling more than 3 div items if needed.
Here is a basic example that uses a state array activeList to handle the changes of z-index, so it is independent to data and can still work if data scales.
It uses the index of the state array to calculate z-index for each item. On click event, it pushes an item to the end of array (so it will have the highest z-index), as a lightweight approach to handle the re-order of z-index.
Forked live demo on: codesandbox
import "./styles.css";
import { useState } from "react";
export default function App() {
const [activeList, setActiveList] = useState([]);
const handleClick = (id) =>
setActiveList((prev) => {
const current = prev.filter((item) => item !== id);
return [...current, id];
});
const data = [
{ id: 1, label: "box 1", class: "box1" },
{ id: 2, label: "box 2", class: "box2" },
{ id: 3, label: "box 3", class: "box3" }
];
return (
<div className="App">
<div className="box-wrapper">
{data.map((b) => {
const activeIndex = activeList.findIndex((id) => id === b.id);
const zIndex = activeIndex >= 0 ? activeIndex + 1 : 0;
return (
<div
className={b.class}
key={b.id}
style={{ zIndex }}
onClick={() => handleClick(b.id)}
>
{b.label}
</div>
);
})}
</div>
</div>
);
}
Hope this could help.
Is there any way to check if the div is at the bottom of the another div (acting as a parent, or container).
What I tried
So basically I made demo where there are child elements (items, setItems) in the div that can be added and deleted and also you can change the height of them by clicking on the divs (important here). Also there is another div, which is not in the items state, where I want to change the title of that item, if it is at the bottom of the his parent div (also items have the same parent as this div has).
Problem with my solution
I have tried something where I am looking at the getBoundingClientRect() of the parent container and this "blue" div, lets call it like that, and it will work fine, ONLY IF the items have the same height, but soon as a delete the one item and change the height of it by clicking on the div, it will not work. It will show that it is on the bottom of the screen (the title will be true) but in reality it is not.
My code
App.js - only for demo purposes
import "./styles.css";
import { useState, useEffect, useRef } from "react";
export default function App() {
const arrayItems = [
{
id: 1,
name: "test",
resized: false
},
{
id: 2,
name: "test1",
resized: false
},
{
id: 3,
name: "test2",
resized: false
}
];
const [items, setItems] = useState(arrayItems);
const [title, setTitle] = useState(false);
const parentRef = useRef(null);
const itemsRef = useRef(null);
useEffect(() => {
if (
parentRef?.current.getBoundingClientRect().bottom -
itemsRef?.current.getBoundingClientRect().height <=
itemsRef?.current.getBoundingClientRect().top
) {
setTitle(true);
} else {
setTitle(false);
}
}, [parentRef, items]);
const handleClick = () => {
const maxValue = Math.max(...items.map((item) => item.id)) + 1;
setItems((prev) => [
...prev,
{ id: maxValue, name: "testValue", resized: false }
]);
};
const handleDelete = () => {
setItems((prev) => prev.slice(0, prev.length - 1));
};
const handleResize = (item) => {
setItems((prev) =>
prev.map((itemOld) => {
if (itemOld.id === item.id) {
return itemOld.resized === true
? { ...itemOld, resized: false }
: { ...itemOld, resized: true };
} else {
return itemOld;
}
})
);
};
console.log(items);
return (
<div className="App">
<button onClick={handleClick}>Add new</button>
<button onClick={handleDelete}>Delete last</button>
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div ref={parentRef} className="container">
{items?.map((item) => {
return (
<div
onClick={() => handleResize(item)}
style={{ height: item.resized ? "70px" : "20px" }}
key={item.id}
className="container-item"
>
<p>{item.name}</p>
</div>
);
})}
<div ref={itemsRef} id="title-div">
{title ? "At the bottom" : "Not at the bottom"}
</div>
</div>
</div>
);
}
styles.css
.App {
font-family: sans-serif;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-top: 1rem;
}
* {
margin: 0;
padding: 0;
}
.container {
width: 600px;
height: 300px;
background-color: gray;
display: flex;
flex-direction: column;
}
.container-item {
width: 100%;
background-color: hotpink;
}
#title-div {
width: 100%;
padding: 1rem;
background-color: blue;
color: white;
}
What I want to make
As the title suggest I want to see if the div is at the bottom of the container/parent div. That is it, and other items in that parent div, cannot interfere with this div, in sense that adding, resizing, deleting those items, will not suddenly change the position of the div that I want to analyse (to see if it is at the bottom of the screen)
I have come up with my own solution and it works always. I just have to deduct the "top" from parentsRef and "top" from the itemsRef, and add to that the clientHeight of the itemsRef. This way it will always be at the bottom of the container, doesnt matter if I delete the items, resize them etc.
The code
useEffect(() => {
if (
parentRef?.current.clientHeight <=
itemsRef?.current.getBoundingClientRect().top -
parentRef?.current.getBoundingClientRect().top +
itemsRef?.current.clientHeight
) {
setTitle(true);
} else {
setTitle(false);
}
}, [parentRef, items, itemsRef]);
In this project, React, TypeScript and ant design are used. In a part of the project, only one box out of three boxes should be selected. I have used "useState" and toggle, but when I select one, they are all selected together when only one should be selected. I am using React version 18.2.0
I would be grateful if you could guide me.
allBox{
display: flex;
align-items: center;
justify-content: space-between;
width: 700px
}
.box{
width: 34px;
height: 34px;
border: 3px solid yellow;
background: green;
color:blue;
}
.box.active{
border: 3px solid black;
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
import React, { useState } from "react";
function MyBox() {
const boxes = [
{
id: 1,
type: "1",
},
{
id: 2,
type: "2",
},
{
id: 3,
type: "3",
},
];
const [boxSelect, setBoxSelect] = useState(false);
const handleSelect = () => {
setBoxSelect(!boxSelect);
};
return (
<div>
<div className='allBox'>
{boxes.map((box) => {
return (
<div className={`${box} ${boxSelect && 'active'}`} key={box.id} onClick={handleSelect}>
<p>{box.type}</p>
</div>
);
})}
</div>
</div>
);
}
export default MyBox;
It's because all your boxes share the same const [boxSelect, setBoxSelect] = useState(false); so if you click on one of them, they will all be selected.
You have two solutions:
create a children component with only:
function mySubBox(box) {
const [boxSelect, setBoxSelect] = useState(false);
const handleSelect = () => {
setBoxSelect(!boxSelect);
};
return (
<div className={`${box} ${boxSelect && 'active'}`} key={box.id} onClick={handleSelect}>
<p>{box.type}</p>
</div>
);
}
And the parent loops through it:
{boxes.map((box, i) => <mySubBox box={box} key={i}/>)}
another solution would be to keep only one component and store the selected boxes in an array: if I click on the 2nd box, my selected array is [2], and you add/remove the item inside the array.
I have a slideshow based on an array of objects with its characteristics, one of them is the background-color of the current slide. I have a property called bg which stores it. This is what I am using to set each background-color, which changes to every image, however I am using an inline style to do that.
I'd like to know if there is a way to do that without using this inline style?
Here is a sample of my code:
import React from 'react'
import { Fragment } from 'react'
import classes from './MainPageHeader.module.css'
const MainPageHeader = props => {
let [minorSlideImg, setMinorSlideImg] = React.useState(0)
let minorSlides = [
{
img: require('../../../assets/images/Header/MinorSlider/imgSolo1-mainpage.png'),
alt: 'Produto 1',
linkText: ['PRODUTO 5', '$ 19.99'],
productId: 5,
bg: 'rgb(151, 105, 105)'
},
{
img: require('../../../assets/images/Header/MinorSlider/imgSolo2-mainpage.png'),
alt: 'Produto 2',
linkText: ['PRODUTO 13', '$ 199.99'],
productId: 13,
bg: '#fad3e0'
},
{
img: require('../../../assets/images/Header/MinorSlider/imgSolo3-mainpage.png'),
alt: 'Produto 3',
linkText: ['PRODUTO 10', '$ 499.99'],
productId: 10,
bg: '#ccc'
},
{
img: require('../../../assets/images/Header/MinorSlider/imgSolo4-mainpage.png'),
alt: 'Produto 4',
linkText: ['PRODUTO 11', '$ 999.99'],
productId: 11,
bg: 'rgb(238, 225, 183)'
},
]
const passSlideHandler = () => {
if (minorSlideImg < minorSlides.length - 1) {
setMinorSlideImg(minorSlideImg + 1)
} else {
setMinorSlideImg(0)
}
}
React.useEffect(() => {
const interval = setTimeout(() => {
passSlideHandler()
}, 5000);
return () => clearTimeout(interval);
});
return (
<Fragment>
<div
className={classes.MinorSlider_subContainer}
style={{backgroundColor: minorSlides[minorSlideImg].bg}} // <= This is what I'd like to remove
>
<img
src={minorSlides[minorSlideImg].img}
alt={"img-1"}
/>
</div>
</Fragment>
)
}
export default MainPageHeader
CSS:
.MinorSlider_subContainer {
height: 65%;
width: 50%;
background-color: #ccc;
}
.MinorSlider_subContainer img {
max-width: 100%;
}
.MinorSlider_subContainer div {
position: relative;
background-color: white;
width: 100%;
height: 65px;
}
.MinorSlider_subContainer div > *{
display: flex;
flex-direction: column;
justify-content: space-evenly;
width: 100%;
height: 100%;
padding-left: 25px;
text-decoration: none;
}
.MinorSlider_subContainer div p {
margin: 0;
color: rgb(75, 75, 75);
}
As can be seen, every five seconds the index of minorSlides changes, therefore, the slide that is being shown changes as well. This index is used to refer to each feature of the current slide.
So, is there a way to remove this inline style and make my JSX cleaner?
If I was using HTML, CSS and JS I could do that with JQuery or even plain JS, but I don't know how to do that here. I know I could create the element with a loop, but I'd like to keep changing only the index and not the whole element.
Here is the sildeshow:
If you can't create a css class for every color, the other option is to add the style tag and override the background-color property:
const subcontainerBackground = `.${classes.MinorSlider_subContainer} { background-color: ${minorSlides[minorSlideImg].bg}}`
return {(
<Fragment>
<style>
{subcontainerBackground}
</style>
<div className={classes.MinorSlider_subContainer} >
//....
</div>
</Fragment>
}
EDIT
Also you can add the style tag using Document.createElement():
useEffect(() => {
const content = `.${classes.MinorSlider_subContainer} { background-color: ${minorSlides[minorSlideImg].bg}}`;
const style = document.createElement("style");
style.innerHTML = content;
document.head.appendChild(style);
return () => document.head.removeChild(style);
}, [minorSlideImg]);
Well it should be alright to use inline styling in this case.
Additionally you can do something like:
{
...
bgClass: 'red'
}
add that class to the div element:
<div className={`classes.MinorSlider_subContainer ${minorSlides[minorSlideImg].bgClass}`} />
and style it in the end:
.red {
background: 'red';
}
Or you can try to use reference
const ref = useRef()
useEffect(() => {
if (ref.current == null) {
return
}
ref.current.style.backgroundColor = minorSlides[minorSlideImg].bg
}, [minorSlideImg, ref])
<div ref={ref} />
Here is my solutions for the same. Except, I add the colours in a list and use the rand function.
Here is the colour list
const color_list = [
"tomato",
"blueviolet",
"cornflowerblue",
"indianred",
"MediumAquaMarine",
"MediumPurple",
"Rebeccapurple",
"sandybrown",
"seagreen",
"palevioletred",
"lightsteelblue",
"Gold",
"teal",
];
I create a variable and add random function to it, to select a bunch of colours.
const rando_color = color_list[Math.floor(Math.random() * color_list.length)];
Simply pass the variable in the style option in the html div tag to dynamically assign background color
<div
p={4}
style={{
backgroundColor: rando_color, // Added variable here
fontFamily: "Oswald",
border: "solid 2px white",
}}
>
<h1>Some Content</h1>
</div>
To make it simple, just add the variable directly in the tag without any curly braces. Also you could try using this variable in a react state for better loading. Add a default prop as well.
I want to know it's normal to reuse react key from component to component. In Row component i got key From column component and reuse it for mapping Row childrens
const Table = props => {
const { data, children, showHeader } = props;
return (
<div className="table">
{showHeader && <TableHead children={children} />}
{data.map(data => {
return <Row key={data.id} data={data} children={children} />;
})}
</div>
);
};
const TableHead = props => {
const { children } = props;
return (
<div className="table-row">
{children.map(col => {
const { title, field, width } = col.props;
return (
<div className="table-col" key={field}>
<div
className="table-cell table-cell-head"
style={{
width: width
}}
>
{title}
</div>
</div>
);
})}
</div>
);
};
//HERE I GET key from Column component and reuse it for rows (number of columns === number of rows)
const Row = props => {
const { data, children } = props;
return (
<div className="table-row">
{children.map(col => {
let { field, ...rest } = col.props;
const { key } = col;
return (
<div className="table-col" key={key}>
{React.cloneElement(col, {
...rest,
field,
data
})}
</div>
);
})}
</div>
);
};
const Column = props => {
const { field, data, width } = props;
return (
<div
style={{
width: width
}}
className="table-cell"
key={data.id}
>
{data[field]}
</div>
);
};
const HeadRow = props => {
const { children } = props;
return (
<div className="table-row">
{children.map(col => {
const { title, field, width } = col.props;
return (
<div className="table-col" key={field}>
<div
className="table-cell table-cell-head"
style={{
width: width
}}
>
{title}
</div>
</div>
);
})}
</div>
);
};
const initData = [
{
id: 1,
name: "Ivan",
age: "My age is 27",
enabled: true,
myListValue: [
{
myName: "Duncan",
myDescription: "Immortal!",
myGroup: "Immortal",
createDate: "2019-08-12T05:21:28Z"
}
],
lastChanged: new Date(),
sortable: true
},
{
id: 2,
name: "Vitaly",
age: `My age is 25\nMy age is 25\nMy age is 25\n`,
lastChanged: new Date(),
enabled: true,
sortable: true
},
{
id: 3,
name: "Sergey",
age: "My age is 29",
enabled: true,
myListValue: [
{
myName: "Duncan",
myDescription: "Immortal!",
myGroup: "Immortal",
createDate: "2019-08-12T05:21:28Z"
},
{
myName: "Connor",
myDescription: "Immortal2!",
myGroup: "MacLeods",
createDate: "2019-08-12T05:21:28Z"
},
{
myName: "John Snow",
myDescription: "(he knows nothing)",
myGroup: "WhiteWalkers",
createDate: "2019-08-12T05:21:28Z"
},
{
myName: "Jamie Lannister",
myDescription: "Lannisters always pay their debts",
myGroup: "Red castle",
createDate: "2019-08-12T05:21:28Z"
}
],
lastChanged: new Date()
}
];
ReactDOM.render(
<Table data={initData} showHeader={true} sortableConfig={{}}>
<Column key="0" field="name" width={150} title="Name" sortable="true" />
<Column key="1" field="age" width={150} title="AGe" sortable="true" />
</Table>, document.getElementById('root'))
.App {
font-family: sans-serif;
text-align: center;
display: flex;
flex-wrap: wrap;
}
.table {
border: 1px solid;
border-bottom: none;
}
.table-row {
width: 100%;
border-bottom: 1px solid;
display: flex;
}
.table-col {
border-right: 1px solid;
}
.table-col:last-child {
border: none;
}
.table-cell {
white-space: pre-line;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
box-sizing: border-box;
}
.table-cell-head {
font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Keys help React identify which items have changed, are added, or are
removed.
Keys should be given to the elements inside the array to give them a stable identity, and they only make sense in the context of the surrounding array, so it doesn't matter if two isolated lists have elements with equal keys as long as they are not equal inside the same list (repeated ids). There is no problem with the following code
{
arr.map((item,index) =>{
//defining key only once per `arr` iteration
const key = uniqueId(index)
return(
<div key={key}>
{
arr2.map((item, index) => <span key={key} />)
}
</div>
)
})
}
Note that the key is only relevant within a particular parent React element. React won’t try to “match up” elements with the same keys between different parents. (React doesn’t have idiomatic support for moving a host instance between different parents without re-creating it.) Font
See the docs here