How to get value from array outside of loop - javascript

How can I get the value of oneHundredColorLevel from the array and render it outside the container of the other colors? Each set of colors should be the boxes for each color, with a separate box for the 100 level color.
Link to codepen
const colorPalette = {
Dark10: "#FEF9E8",
Dark20: "#FDF4DE",
Dark30: "#FCEFCC",
Dark40: "#F7E0A2",
Dark50: "#F0CC72",
Dark60: "#D5B363",
Dark70: "#C7A55E",
Dark80: "#B39553",
Dark90: "#9D8240",
Dark100: "#89723E",
Dark110: "#7C6737",
Dark120: "#715E32",
Dark130: "#66552E",
Dark140: "#5B4A28"
};
const ColorSwatches = ({ colors, shade }) => {
let filtered = Object.fromEntries(
Object.entries(colors).filter(([key, value]) => key.includes(shade))
);
let onehundredcolor = [];
return (
<div class="wrapper">
<div class="bigNumber">
<h1>{onehundredcolor}</h1><----SHOULD BE NAME ONLY
<p>{onehundredcolor}</p><----SHOULD BE HEX VALUE ONLY
</div>
{Object.entries(filtered).map((color, i) => {
if (i === 9) {
onehundredcolor.push(color);
console.log(onehundredcolor)
}else if(i !== 9) {
return (
<div key={i} style={{ backgroundColor: `${color[1]}` }}>
<h2>{color[0]}</h2>
<p>HEX {color[1]}</p>
</div>
);
}
})
</div>
);
};

I think that an array would be a more flexible container here than an object whose properties are the various shade/color pairs. For example:
const colors = [
{shade: 'dark', color: '#FEF9E8'},
{shade: 'dark', color: '#FDF4DE'},
...
{shade: 'light', color: '#111111'},
{shade: 'light', color: '#111122'},
...
];
Then you can filter/map as you see fit, for example:
const darkColors = colors.filter(c => c.shade === 'dark');
const lightColors = colors.filter(c => c.shade === 'light');
And you can easily access the 10th dark color via:
darkColors[9]

Related

React Leaflet with LayersControl handling object datas

I'd like to have a map using OpenStreetMap showing location of flowers. My point is to have LayersControl with colours and type and be able to check for example Orange and Tulip and see only orange tulips on the map but it seems hard from what i read on React LeafLet documentation.
To be easier to understand i will add some code :
Flower datas example:
const flowers = [
{
"type": "Tulip",
"colour": "Orange",
"latlng": [52.081222, 5.235965],
},
{
"type": "Crocus",
"colour": "Red",
"latlng": [52.081421, 5.235534],
},
]
LeafletMap.jsx (Partial):
const LeafletMap: React.FC = () => {
return (
<MapContainer id="mapId"
center={averagePos}
zoom={zoom}>
{flowerItems.map((flower, index) => (
//Maybe do something here like sorting and creating
//multiple layers
//or having already a layer for every type of search
//but if i want to add more colours ou type it can be very hard to update
))}
</LayersControl>
</MapContainer>
)
}
You could maintain the selected layers using state variables - one array to track the type (Crocus or Tulip) and another to track the colour (red or orange). Initially, the states are setup to show everything:
const [type, setType] = useState(['Tulip', 'Crocus']);
const [colour, setColour] = useState(['Orange', 'Red']);
For each type and colour you could create a LayersControl where you hook into the add and remove event handlers and update the corresponding state (type or colour) when the layer is checked or unchecked by the user:
<LayersControl.Overlay name="Crocus" checked="true">
<LayerGroup
eventHandlers={{
add: (e) => {
updateTypeState('Crocus', true);
},
remove: (e) => {
updateTypeState('Crocus', false);
},
}}
></LayerGroup>
</LayersControl.Overlay>
The functions to update the state look like this (there is one function for updating type and one for updating colour):
const updateTypeState = (key: string, value: boolean) => {
setType((prevState) => {
if (value) {
prevState = [...prevState, key];
} else {
prevState = prevState.filter((e) => e !== key);
}
console.log(prevState);
return prevState;
});
};
const updateColourState = (key: string, value: boolean) => {
setColour((prevState) => {
if (value) {
prevState = [...prevState, key];
} else {
prevState = prevState.filter((e) => e !== key);
}
return prevState;
});
};
You could then render the markers using the map function as you suggested:
{flowers
.filter((flower) => {
if (type.length == 0 && colour.length == 0) {
// No layers selected, so show all
return true;
}
if (type.length > 0 && colour.length > 0) {
// Colours and types selected
return (
type.indexOf(flower.type) >= 0 &&
colour.indexOf(flower.colour) >= 0
);
}
if (type.length > 0) {
// Type selected, no colour selected
return type.indexOf(flower.type) >= 0;
}
// Colour selected, no type selected
return colour.indexOf(flower.colour) >= 0;
})
.map((flower, index) => (
<Marker position={flower.latlng}>
<Popup>
{flower.type}, {flower.colour}
</Popup>
</Marker>
))}
There's a working StackBlitz here, but please note the marker images do not display properly due to this issue, but you should be able to see a broken image icon and click on it to view details of the flower.

Not able to change svg elements color by looping

I'm trying to change the color of svg elements by comparing the id's of the elements with an array. I'm getting the correct comparison results by looping the id's of all the available elements and comparing them with the array data. However, I'm not able to dynamically color the compared element.
This is what I have tried so far: CodeSandBox
import React from "react";
import "./App.css";
import NewTestColor from "./NewTestColor";
const App = () => {
const data = [
{
id: "D",
hmc: "",
lmc: "low"
},
{
id: "B",
hmc: "high",
lmc: ""
},
{
id: "A",
hmc: "high",
lmc: ""
},
{
id: "C",
hmc: "",
lmc: "low"
}
];
const addEventListener =
("mouseup",
(e) => {
// Let's pick a random color between #000000 and #FFFFFF
const rnd = Math.round(Math.random() * 0xffffff);
// Let's format the color to fit CSS requirements
const fill = "#" + rnd.toString(16).padStart(6, "0");
// Let's apply our color in the
// element we actually clicked on
e.target.style.fill = fill;
const id = e.target.getAttribute("id");
console.log(id);
console.log(fill);
// console.log(data);
});
// const Ndata = data.filter(task => task.hmc === "high")
// .map(filteredData => {filteredData.id}, {filteredData.hmc}, {filteredData.color} )
const FilteredData = data.filter((e) => e.hmc.includes("high"));
const OnlyIp = FilteredData.map((e) => `${e.id} ${e.hmc}`);
// console.log(OnlyIp)
console.log(FilteredData);
return (
<div>
<NewTestColor onClick={addEventListener} items={FilteredData} />
</div>
);
};
export default App;
The issue is if you define onClick as a prop on a component you defined it does not work. You need to add it to an actual element like svg.
Change the NewTestColor to pass to onClick function to outer svg
const NewTestColor = ({ onClick }) => (
<svg viewBox="0 0 210 297" height={500} width={500} onClick={onClick}>
...
...
...
</svg>
);
And the addEventListener function in App.js should look like below.
const addEventListener = (e) => {
// Let's pick a random color between #000000 and #FFFFFF
const rnd = Math.round(Math.random() * 0xffffff);
// Let's format the color to fit CSS requirements
const fill = "#" + rnd.toString(16).padStart(6, "0");
// Let's apply our color in the
// element we actually clicked on
e.target.style.fill = fill;
const id = e.target.getAttribute("id");
console.log(id);
console.log(fill);
// console.log(data);
};
Code sandbox

array map split join, javascript

I need help in understanding this piece of code.
What is it doing and what is the type its returning. Possibly break it in smaller chunks to understand.
Why would it join array elements on '.' and then split them using the same dilimentor'.' What type of array is being passed back from search results?
function getRandomInt(max, min = 0) {
return Math.floor(Math.random() * (max - min + 1)) + min; // eslint-disable-line no-mixed-operators
}
const searchResult = query =>
new Array(getRandomInt(5))
.join('.')
.split('.')
.map((item, idx) => {
const category = `${query}${idx}`;
return {
value: category,
label: (
<div
style={{
display: 'flex',
justifyContent: 'space-between',
}}
>
<span>
Found {query} on{' '}
<a
href={`https://s.taobao.com/search?q=${query}`}
target="_blank"
rel="noopener noreferrer"
>
{category}
</a>
</span>
<span>{getRandomInt(200, 100)} results</span>
</div>
),
};
});
its been called like this
const [options, setOptions] = useState<SelectProps<unknown>["options"]>([]);
const handleSearch = (value: string) => {
setOptions(value ? searchResult(value) : []);
};
I want to be able to put console.log to see what value is setOptions getting.
Thanks
----------------- Update 2-----------------
const searchResult = (query: string) => {
const myArray = new Array(getRandomInt(5)).fill(0).map((item, idx) => {
const category = `${query}${idx}`;
return {
value: category,
label: labelElement(query, category),
};
});
console.log(myArray);
return myArray;
};
const labelElement = (query: string, category: string) => {
return (
<div
style={{
display: "flex",
justifyContent: "space-between",
}}
>
<span>
Found {query} on <a>{category}</a>
</span>
<span>{getRandomInt(200, 100)} results</span>
</div>
);
};
const [options, setOptions] = useState<SelectProps<unknown>["options"]>([]);
const handleSearch = (value: string) => {
setOptions(value ? searchResult(value) : []);
};
If we translate what searchResult does in plain English, I think it will be something like this:
Generate & return an array of objects which length should be between 0 and 5 (including both values).
Objects in array should have this shape:
{
value: string,
label: JSX.Element
}
The trick with .join('.').split('.') seems to be needed to make array iterable with .map.
If you try to call new Array(5).map(() => 'I am ignored 😐') you will see that you'll get an empty array, and .map(...) part will be simply ignored.
That happens because new Array(5) returns an array of empty cells which are ignored by .map(...). A more usual way to deal with it would be something like this:
new Array(5).fill().map(() => 'Now it works!');

Is there any way to export/pass a state variable to an external CSS file in ReactJS

const Dropdown = ({ options, selected, onSelectedChange }) => {
const [ open, setopen ] = useState(false);
const renderedOptions = options.map((option) => {
if (option.value === selected.value) {
return null;
}
return (
<div key={option.value} className="item" onClick={() => onSelectedChange(option)}>
{option.label}
</div>
);
});
return (
<div className="ui form">
<div className="field">
<label className="label">Select a color</label>
<div onClick={() => setopen(!open)} className={`ui selection dropdown ${open ? 'visible active' : ''}`}>
<i className="dropdown icon" />
<div className="text">{selected.label}</div>
<div className={`menu ${open ? 'visible transition' : ''}`}>{renderedOptions}</div>
</div>
</div>
//Here is the selected.value state (value contains string of color name
{<div style={{ color: `${selected.value}` }}>{selected.value}</div>}
</div>
);
};
export default Dropdown;
const options = [
{
label: 'The Color Red',
value: 'red'
},
{
label: 'The Color Green',
value: 'green'
},
{
label: 'The Color Blue',
value: 'blue'
}
];
How can I use the selected.value in an external CSS file?
The data in the selected.value is a string of color name(s).
You can probably use Styled Components if that's what you're looking for, just an example, not really well thought out. The component can be in another file
const HoveredLink = styled.span`
color: ${props => props.selected ? 'black' : 'rgb(150, 153, 156)'};
`
<HoveredLink selected={\\someconditionhere} > Hover me <HoveredLink/>
You can simple use as a variable, this is not exactly CSS. So this one should work:
<div style={{color: selected.value}} >{ selected.label } </div>
You can also set style as a new variable:
const Dropdown = ({options,...}) => {
const styleDiv = {
color: options.value
}
//...
return (
//...
<div style={styleDiv}> {options.label} </div>
)
}
Here is how I solved it by using concept from this URL
import styles from './colorchange.css';
//...
//For setting default value (and closing dropdown when clicked outside)
useEffect(() => {
document.body.addEventListener('click', (event) => {
if (ref.current.contains(event.target)) {
return;
}
setopen(false);
});
document.documentElement.style.setProperty(`--variablename`, selected.value);
}, []);
//...
//inside renderedoption
return (
<div
key={option.value}
className="item"
onClick={() => {
onSelectedChange(option);
document.documentElement.style.setProperty(`--variablename`, option.value);
}}
>
{option.label}
</div>
);
//....
//for printing the color
<div className="colorcolor">This text is: {selected.value}</div>
CSS FILE:
{
--variablename: default;
}
.colorcolor {
color: var(--variablename);
}
Another way using CSS stylesheet.
Usually when I need to pass a value to use it for CSS I'll
go for specific CSS classes as I rather use the stylesheet
for style ( !== style within component ) for scalability reasons &
ease to access. If it can help ...
I. Known values case / no need to convert into word
to expect ( seems like it should be either [ blue,red,green ])
<div className = { selected.value } />
II. Need to convert into word
Let's say you need to change a selected.value that could be an hexadecimal value, you'll need to associate a word className you could use for CSS later on.
This is just an example and you can do a lot more within the expression passed
// convert anticipated value to the word you need
const colors = {'#F00': 'red', '#0F0' : green, '#00F': 'blue'};
<div className = { colors[ selected.value ] } />
📌Applied example
import './style.css' // style.css as same level of your component
const Dropdown = ({options,...}) => {
// if need to make wording *(cf:. case )
// const color = {'#F00': 'red', '#0F0' : green, '#00F': 'blue'};
//...
return (
//...
// if need to make wording *(cf:. case )
// <div className = { colors[ selected.value ] }> { selected.value } </div> */ }
<div className = { selected.value }> { selected.value } </div>
)
}
CSS for the above cases.
/*CSS file: style.css*/
.red { ...code... }
.green { ...code... }
.blue { ...code... }

Rendering react in a conditional for loop

I have a static information in web page.
class MyStaticWebPage extends React.Component {
render() {
return (
<TopContainer>
<IconListContainer>
<LeftButton
Icon={MyIcon1}
color="#ffffff"
text="text1"
/>
<CenterButton
Icon={MyIcon2}
color="#eeeeee"
text="text2"
/>
<RightButton
Icon={MyIcon3}
color="#dddddd"
text="text3"
/>
</IconListContainer>
<IconListContainer>
<LeftButton
Icon={MyIcon4}
color="#cccccc"
text="text4"
/>
</IconListContainer>
</TopContainer>
);
}
}
This page is statically display in a row list, per line maximum three icons, and now I want to turn them dynamically, suppose I store icon props in a props array.
[
{
icon: 'MyIcon1',
color: '#ffffff',
text: 'text1'
},
{
icon: 'MyIcon2',
color: '#eeeeee',
text: 'text2'
},
{
icon: 'MyIcon3',
color: '#dddddd',
text: 'text3'
},
{
icon: 'MyIcon4',
color: '#cccccc',
text: 'text4'
}
]
Finally make page automatically rendered using this props array.
class MyStaticWebPage extends React.Component {
render() {
var rows = []
for (var i = 0; i <= parseInt(iconNum / 3); i++) {
// row level for loop
// rows.push(row)
for (var j = iconNum; j % 3 !== 0; j--) {
// icon level for loop
// rows.push(icon)
}
}
return (
<TopContainer>
{rows}
</TopContainer>
);
}
}
How to do with this through realistic react code?
Given you have a flat array but want to render it in rows of three the first thing you should do is chunk the array. Lodash has a method for this or you can do a simple enough reduce on your array.
const chunkedArray = icons.reduce((reduction, icon, index) => {
index % 3 ? reduction[reduction.length - 1].push(icon) : reduction.push([icon])
return reduction
}, [])
Now you have your data in the right shape we can easily map that to output jsx.
class IconListWrapper extends React.Component {
render() {
const { subList } = this.props
const buttonTypes = ['LeftButton', 'CenterButton', 'RightButton']
const Element = buttonTypes[index]
return (
<IconListContainer>
{subList.map((icon, index) => <Element
Icon={MyIcon1}
color="#ffffff"
text="text1"
/>)}
</IconListContainer>
);
}
}
class MyStaticWebPage extends React.Component {
render() {
return (
<TopContainer>
{chunkedArray.map((subList) => <IconListWrapper subList={subList} />)}
</TopContainer>
);
}
}
I think you're asking how to make sure you group the icons into groups of three using LeftButton, CenterButton, and RightButton.
I'll assume you start with something like this:
var icons = [
{
icon: 'MyIcon1',
color: '#ffffff',
text: 'text1'
},
{
icon: 'MyIcon2',
color: '#eeeeee',
text: 'text2'
},
{
icon: 'MyIcon3',
color: '#dddddd',
text: 'text3'
},
{
icon: 'MyIcon4',
color: '#cccccc',
text: 'text4'
}
];
then, see comments:
class MyStaticWebPage extends React.Component {
var buttonTypes = [LeftButton, CenterButton, RightButton];
render() {
var rows = [];
var children = [];
for (var i = 0; i < icons.length; i++) {
// x will be 0, 1, or 2
var x = i % 3;
// Get the button type to use
var buttonType = buttonTypes[x];
// Create the button using `createElement`
children.push(React.createElement(buttonType, icons[i]);
// If this is the last button of three, add these in a container
// and get a new array for children
if (x == 2) {
rows.push(<IconContainer>{children}</IconContianer>);
children = [];
}
}
// Handle any remaining children
if (children.length) {
rows.push(<IconContainer>{children}</IconContianer>);
}
return (
<TopContainer>
{rows}
</TopContainer>
);
}
}
As pointed out in other answers - the loop can be achieved with map function. To display them dynamically, you may wish to take a look at flexbox and use them in css.
One possible way of writing is like this:
var buttonTypes = [LeftButton, CenterButton, RightButton];
let table = [];
arr.forEach((el, i) => {
let Component = buttonTypes[i%3];
rows.push(
<Component
Icon={el.icon}
text={el.text}
color={el.color}
/>
)
if(i%3 == 2) {
table.push( <IconListContainer> {rows} </IconListContainer> )
rows = [];
}
})
if (rows.length) {
table.push( <IconListContainer> {rows} </IconListContainer> );
}
return (
<TopContainer>
{table}
</TopContainer>
);
You can try something like this.
const icons = [
{
icon: 'MyIcon1',
color: '#ffffff',
text: 'text1'
},
{
icon: 'MyIcon2',
color: '#eeeeee',
text: 'text2'
},
{
icon: 'MyIcon3',
color: '#dddddd',
text: 'text3'
},
{
icon: 'MyIcon4',
color: '#cccccc',
text: 'text4'
}
];
class MyStaticWebPage extends React.Component {
const menu = [
({ icon, color, text }) => (<LeftButton Icon={icon} color={color} text={text} />),
({ icon, color, text }) => (<CenterButton Icon={icon} color={color} text={text} />),
({ icon, color, text }) => (<RightButton Icon={icon} color={color} text={text} />)
];
render() {
return (
<TopContainer>
<IconListContainer>
{icons && icons.map((icon, i) => menu[i % 3](icon))}
</IconListContainer>
</TopContainer>
);
}
}

Categories