React js components dependency - javascript

I have a question regarding what is the best structure for a react component which is composed from another components.
So the first one is :
<ColorSelect id="color"
label={this.state.selectLabel}
trigger={{ color: "lime", text: "Lime"}}
onPropagateClick={this.changed}>
<ColorOption color="yellow" text="Yellow" onPropagateClick={ColorSelect.optionClicked}/>
<ColorOption color="orange" text="Orange" onPropagateClick={ColorSelect.optionClicked}/>
<ColorOption color="red" text="Red" onPropagateClick={ColorSelect.optionClicked}/>
</ColorSelect>
here the problem is that I cannot access the ColorSelect functions from ColorOption
and second :
<ColorSelect id="color"
label={this.state.selectLabel}
trigger={{ color: "lime", text: "Lime"}}
onPropagateClick={this.changed}>
options={[
{ color: "yellow", text: "Yellow" },
{ color: "orange", text: "Orange" },I have a question regarding what is the best structure for a react component which is composed from another components.
So the first one is :
<ColorSelect id="color"
label={this.state.selectLabel}
trigger={{ color: "lime", text: "Lime"}}
onPropagateClick={this.changed}>
<ColorOption color="yellow" text="Yellow" onPropagateClick={ColorSelect.optionClicked}/>
<ColorOption color="orange" text="Orange" onPropagateClick={ColorSelect.optionClicked}/>
<ColorOption color="red" text="Red" onPropagateClick={ColorSelect.optionClicked}/>
</ColorSelect>
here the problem is that I cannot access the ColorSelect functions from ColorOption
and second :
<ColorSelect id="color"
label={this.state.selectLabel}
trigger={{ color: "lime", text: "Lime"}}
onPropagateClick={this.changed}>
options={[
{ color: "yellow", text: "Yellow" },
{ color: "orange", text: "Orange" },
{ color: "red", text: "Red"} />
In these example the component is not easy to reuse because I want to have a component where I can send the properties in json format

A component sees only its one props, but its parent can pass a method as a prop. This is how you may write ColorOption.
var ColorOption = React.createClass({
render: function() {
return <div style={{color: this.props.color}}
onClick={this.props.onSelect.bind(null, this.props.text)}
>{this.props.text}</div>
}
})
Notice that when the div emits a click event, ColorOption calls its onSelect prop (with its text prop as argument). onSelect must be passed by the parent, and this is exactly what ColorSelect does.
var ColorSelect = React.createClass({
handleSelect: function(text) {
console.log('Color selected:', text)
},
render: function() {
var options = this.props.options.map(function(option) {
return <ColorOption key={option.color} color={option.color}
text={option.text} onSelect={this.handleSelect} />
}.bind(this))
return <div>{options}</div>
}
})
ColorSelect takes an options prop, which must be an array, and turns it into an array of ColorOptions. Moreover, it passes its handleSelect method to each child, so that they can call it.
var options = [
{ color: "yellow", text: "Yellow" },
{ color: "orange", text: "Orange" },
{ color: "red", text: "Red"},
]
React.renderComponent(<ColorSelect options={options} />, document.body)
That's it.

Related

javascript function giving different results in console and html page

function removeRed(foodArray) {
return foodArray.filter(function (food) {
return food.color !== "red";
});
}
document.write(
removeRed([
{ name: "Apple", color: "red" },
{ name: "Egg", color: "white" },
{ name: "orange", color: "orange" },
])
);
console.log(
removeRed([
{ name: "Apple", color: "red" },
{ name: "Egg", color: "white" },
{ name: "orange", color: "orange" },
])
);`
I am getting the desired result in the console log but the document.write is giving the output-"[object Object],[object Object] "
Can someone explain to me what is going on?your text
The simplest answer would be that console. log("") outputs whatever is passed as the parameter. document. write("") adds whatever you want to html.

React - Change size of icon received as props

I have the following component:
import ListItemButton from '#mui/material/ListItemButton';
import ListItemIcon from '#mui/material/ListItemIcon';
import Tooltip from '#mui/material/Tooltip';
const MenuItem = ({data, onClick}) => {
const menuItemOnClick = () => {
onClick(data);
};
const style = {
display: "flex",
justifyContent: "center",
color: "white",
margin:"auto"
};
return (
<Tooltip title={data.friendlyName} placement="right">
<ListItemButton onClick={menuItemOnClick}>
<ListItemIcon sx={style}>
{data.icon}
</ListItemIcon>
</ListItemButton>
</Tooltip>
);
};
export default MenuItem;
The prop is being passed the following way:
myArray.map(entityTypeData => <MenuItem key={entityTypeData.name} data = {entityTypeData} onClick={onClick} />)
myArray is defined like this:
return [
{
name: "X",
friendlyName: "X",
icon: <MedicationIcon />,
entities: []
},
{
name: "Y",
friendlyName: "Y",
icon: <BiotechIcon />,
entities: []
},
...
];
Further information:
Preferably I want to avoid styling my icon where the array is declared, as this is something for which I want to enforce only when the MenuItem Component is used.
I tried changing the size of the parents, but it doesn't cascade to the child icon.
How can I change the height/width of the icon received as props?
It's very similar of what you already did for styling the <ListItemIcon> but you need to do it on the Icon it self. For example look at the code bellow:
Create the style object:
const iconStyle = {
fontSize: "40px"
};
And in your myArray apply the style using the sx prop
return [
{
name: "X",
friendlyName: "X",
icon: <MedicationIcon sx={iconStyle} />,
entities: []
},
{
name: "Y",
friendlyName: "Y",
icon: <BiotechIcon sx={iconStyle} />,
entities: []
},
...
];
UPDATED
Or based on your comment you can use the existing styling for the <ListItemIcon> like this:
const style = {
display: "flex",
justifyContent: "center",
color: "red",
margin: "auto",
"& svg": {
fontSize: "40px",
}
};
Here is a working codesandbox with an example

How to Filter Quantity By Attribute in ReactJs

I'm attempting to create a quantity filter based on color, size, or both. When I click the red color, for example, it displays the whole quantity of the red color, but if I press color red and size small, it displays the exact quantity I require. Is there a way to accomplish this?
This is what I mean.
When I select a color or a size, the quantity should be displayed. Also, there should not be a duplication of my error, since there are three red colors listed above the image.
Code
import React, { useState } from "react";
export default function ControlledRadios() {
const [qty, setQty] = useState(0);
const data = [
{
id: 1,
name: "Product A",
attributes: [
{
id: 1,
color: "Red",
size: "Small",
qty: 200,
},
{
id: 2,
color: "Red",
size: "Medium",
qty: 100,
},
{
id: 3,
color: "Red",
size: "Large",
qty: 300,
},
{
id: 4,
color: "Yellow",
size: "Small",
qty: 200,
},
{
id: 5,
color: "Yellow",
size: "Medium",
qty: 100,
},
{
id: 6,
color: "Yellow",
size: "Large",
qty: 300,
},
],
},
];
const handleChange = (event) => {
setQty(event.target.value);
};
return (
<>
<h1>Quantity: {qty}</h1>
<fieldset value={qty} onChange={(event) => handleChange(event)}>
<h3>Color:</h3>
{data?.map(({ attributes }) => {
return attributes.map(({ id, ...rest }) => (
<>
<label key={id}>
<input
type="radio"
name="schedule-weekly-option"
value={rest.qty}
/>
{rest.color}
</label>
<br />
</>
));
})}
<h3>Size:</h3>
{data?.map(({ attributes }) => {
return attributes.map(({ id, ...rest }) => (
<>
<label key={id}>
<input
type="radio"
name="schedule-weekly-option"
value={rest.qty}
/>
{rest.size}
</label>
<br />
</>
));
})}
</fieldset>
</>
);
}
As seen in the data value, I have multiple color and sizes goes something like this for example {color: "Red", Size: "Small", qty: 200} I have multiple red values, so right every red should be added so when I click the Red radio button it should display the quantity 600 because the quantity of all the red will be added. but if I press like color Red and size Small it should display 200.
PS: If possible can u not make duplicate of colors like I did 3 color red and yellow, to make it only 1 Red and 1 Yellow same goes with the size.
If you need anymore clarification you need or explanation please comment down below. Thanks
Phew! This should do the trick. The idea is to pass more data to your handleChange handleChange - see how I changed it? I grab the data straight out of the target element, which is not ideal, but works.
I didn't do the filtering for you, good luck with that :) Should be just adding a (granted, a fairly complex) .filter(...) to your .map(...).
document.onreadystatechange = () => {
const {useState} = React;
function ControlledRadios() {
const [qty, setQty] = useState(0);
const data = [
{
id: 1,
name: "Product A",
attributes: [
{
id: 1,
color: "Red",
size: "Small",
qty: 200,
},
{
id: 2,
color: "Red",
size: "Medium",
qty: 100,
},
{
id: 3,
color: "Red",
size: "Large",
qty: 300,
},
{
id: 4,
color: "Yellow",
size: "Small",
qty: 200,
},
{
id: 5,
color: "Yellow",
size: "Medium",
qty: 100,
},
{
id: 6,
color: "Yellow",
size: "Large",
qty: 999,
},
],
},
];
const handleChange = (event) => {
const id = event.target.value;
const targetAttribute = data[0].attributes.find(x => x.id == id);
if (event.target.name === "schedule-weekly-option-color") {
let sum = 0;
data[0].attributes.forEach((a) => {
if (a.color===targetAttribute.color) {
sum += a.qty;
}
});
setQty(sum);
} else {
let sum = 0;
data[0].attributes.forEach((a) => {
if (a.color===targetAttribute.color && a.size===targetAttribute.size) {
sum += a.qty;
}
});
setQty(sum);
}
};
return (
<React.Fragment>
<h1>Quantity: {qty}</h1>
<fieldset value={qty} onChange={(event) => handleChange(event)}>
<h3>Color:</h3>
{data.map(({ attributes }) => {
return attributes.map(a => (
<label key={a.id}>
<input
type="radio"
name="schedule-weekly-option-color"
value={a.id}
/>
{a.color}
</label>
));
})}
<h3>Size:</h3>
{data.map(item => {
return item.attributes.map(a => (
<label key={a.id}>
<input
type="radio"
name="schedule-weekly-option-size"
value={a.id}
/>
{a.size}
</label>
));
})}
</fieldset>
</React.Fragment>
);
}
ReactDOM.render(<ControlledRadios />, document.body);
};
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>

how can i add object in array which is in object as property (react.js )

first off, sorry for the confusing title. I couldn't find a way to say this more clearly.
These days, I'm working on my own project and face a problem. If you can give me some
advice, it would be a huge help for me.
So, this is my State
const[state, setState] = useState({
externalEvents: [
{ title: "Art 1", color: "#0097a7", id: 34432, custom: "fdsfdsfds" },
{ title: "Art 2", color: "#f44336", id: 323232 },
{ title: "Art 3", color: "#f57f17", id: 1111 },
{ title: "Art 4", color: "#90a4ae", id: 432432 },
]
});
and this is my input tags and function
<form className="todoinput" onSubmit={addTodo} >
<input type="text" value={title} onChange={e=>setTitle(e.target.value)} placeholder="Add event" />
<input type="text" value={custom} onChange={e=>setCustom(e.target.value)} placeholder="detail" />
<select>
<option value={()=>{setColor('blue')}}>blue</option>
<option value={()=>{setColor('orange')}}>orange</option>
<option value={()=>{setColor('green')}}>green</option>
<option value={()=>{setColor('purple')}}>purple</option>
</select>
<button type="submit">Add todo</button>
</form>
const addTodo = (e) =>{
e.preventDefault();
setState([...state.externalEvents,{title:{title}, color: {color}, custom: {custom}}])
setTitle('')
setCustom('')
}
This is what I wanted to make: I type title,custom and select color in input and select tags. And I submit it, then function is going to add new object in externalEvents(array)
I used spread to do this, but somehow it didn't work and console says "TypeError: Cannot read property 'map' of undefined"
<div id="external-events">
{state.externalEvents.map((event) => (
<div
className="fc-event"
title={event.title}
data-id={event.id}
data-color={event.color}
data-custom={event.custom}
key={event.id}
style={{
backgroundColor: event.color,
borderColor: event.color,
cursor: "pointer"
}}
>{event.title}</div>
))}
</div>
this is a part where map() happen, I think the reason map couldn't read property is because
I failed to send proper property to externalEvents.
thanks for reading, and your help will be appreciated.
p.s I used FullCalendar library!
When you initialized your state, it was an object with a key externalEvents which is an array
useState({
externalEvents: [
{ title: "Art 1", color: "#0097a7", id: 34432, custom: "fdsfdsfds" },
{ title: "Art 2", color: "#f44336", id: 323232 },
{ title: "Art 3", color: "#f57f17", id: 1111 },
{ title: "Art 4", color: "#90a4ae", id: 432432 },
]
})
But when you update your state, it is an array
setState([...state.externalEvents,{title:{title}, color: {color}, custom: {custom}}])
So based on your initial state, setState should be as below
setState({
...state,
externalEvents: [
...state.externalEvents,
{title, color, custom}
]})
Do note that {title, color, custom} is probably what you want, instead of {title: {title}, xxxx
Your problem is probably inside of your addTodo function.
This function sets state to be an array. Following this, state.externalEvents no longer exists.
To test this, try console.log(state) after it has been set in addTodo function.
Based on your intent, here is a modification of your addTodo function that may solve your problem:
const addTodo = (e) =>{
e.preventDefault();
// Use previous state, and make sure to return an object with an 'externalEvents' key as the new state
setState((prevState) => {
const newEvent = {} // whatever your new event is
return { externalEvents: [...prevState.externalEvents, newEvent] }
})
setTitle('')
setCustom('')
}
Further improvement
Furthermore, you can make things more simple by directly having an externalEvents piece of state, to remove the need for a nested externalEvents property inside some other state object.
For example:
const [externalEvents, setExternalEvents] = useState([
{ title: "Art 1", color: "#0097a7", id: 34432, custom: "fdsfdsfds" },
{ title: "Art 2", color: "#f44336", id: 323232 },
{ title: "Art 3", color: "#f57f17", id: 1111 },
{ title: "Art 4", color: "#90a4ae", id: 432432 }
])
If you adopt this, you would need to update your addTodo function once again, specifically the state update step.
Your state update step will now look like this:
setExternalEvents((prevExternalEvents) => {
const newEvent = {} // whatever your new event is
return [...prevExternalEvents, newEvent]
})
See here for more:
Setting state based on the previous state: useState hook, setState function. Accessing previous state value
I think that the issue is that you defined state as an object, with the key externalEvents, which is an array. But when you are submitting the form, in the setState function, you are setting an array, not the original shape.
I recommend you to do it like this:
const [externalEvents, setExternalEvents] = useState([
{ title: "Art 1", color: "#0097a7", id: 34432, custom: "foo" },
{ title: "Art 2", color: "#f44336", id: 323232 },
{ title: "Art 3", color: "#f57f17", id: 1111 },
{ title: "Art 4", color: "#90a4ae", id: 432432 },
]);
And in the form:
const addTodo = (e) => {
...
setExternalEvents(prev => [...prev, {title, color, custom}])
...
}

How can i grab one of my elements in the array and style it?

Hi devs im learning React and i want to know if there's a method to grab an element from my array
and style it with css.
const card = [
{
id: 1,
title: "DEEP EARTH",
Background: "images/earth.jpg",
},
{
id: 2,
title: "NIGHT ARCADE",
Background: "images/arcade.jpg",
},
{
id: 3,
title: "SOCCER TEAM VR",
Background: "images/soccer.jpg",
}
]
As early was said you can use map and inline styles
return (<div>
{card.map((item) => (
<div key={item.id}>{item.title}
styles={{background:url(item.src)}}
>
</div>
))}
</div>);
You will need to render this using map, and then you could apply any css you want with it.
this might help:
https://reactjs.org/docs/lists-and-keys.html
you could add a property to the ones you want styled:
const card = [
{
id: 1,
title: "DEEP EARTH",
Background: "images/earth.jpg",
style: {"color": "red"}
},
{
id: 2,
title: "NIGHT ARCADE",
Background: "images/arcade.jpg",
},
];
and then use map:
{
card.map((cardItem, index) => {
return <div>
<span style={cardItem.style}>{cardItem.title}</span>
</div>
})
}
and in the same manner you could have that property point to a css class you have defined and use className.

Categories