map function running multiple times - javascript

I am using map function on this
<div className="about-sports">
<AboutHead head="Sports" />
<div className="sport-cards">
<Slider {...settings}>
{response.sport.map((sport, key) => {
return (
<div className="sport-card" key={key}>
<Card sx={{ maxWidth: 100 }}>
<CardMedia
component="img"
alt={sport.name}
height="100"
image={sport.sportImgURL}
className="about-img"
/>
<CardContent className="logo-name">{sport.name}</CardContent>
</Card>
</div>
);
})}
</Slider>
</div>
<Line width="100%" marginTop="15px" marginLeft="0px" />
</div>
response is state which contaions
sport: Array [ {…}, {…} ]
0: Object { id: "1526fad5-d14a-4636-b259-1c3f366bce9c", sports_id: "52304670-9efd-4b95-9799-c782ea8907c4", name: "Cricket", … }
1: Object { id: "5cdbc516-a78b-469b-9036-58cea1478d5d", sports_id: "08c56898-3a4e-4b07-86bc-101a0542253f", name: "Chess", … }
length: 2
as given length is 2 but component showing 4 cards

Related

React Formik FieldArray error : A component is changing a controlled input to be uncontrolled

I have a form built with Formik containing an array of objects. When I add a second element to the form with the add-button, I get the following error:
Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
I have made sure that initial values is defined for the the form. I use the FieldArray component from formik. If I remove the time and rate fields, so it's only the name input in each object, I don't get the error, but when I add the time and rate fields, the error occurs. The component contains the following:
const TimeItemsForm = () => {
const jiraItemsStore = useJiraItemsStore();
function jiraTimeImported(timeItemIndex: number, importedHoursTotal: number, checkedItems: CheckedTimeItems) {
// Add checked items to store
jiraItemsStore.setJiraTable(timeItemIndex, checkedItems, importedHoursTotal);
}
const TimeItemSchema = Yup.object().shape({
name: Yup.string().required('Required'),
time: Yup.number().min(0).required('Required'),
// rate: Yup.number().min(0).required('Required'),
});
const TimeItemsSchema = Yup.object().shape({
timeItems: Yup.array().of(TimeItemSchema),
})
const initialValues = {
timeItems: [
{
name: '',
time: 0,
rate: 0,
},
],
};
return (
<>
<Formik
validateOnChange={false}
initialValues={initialValues}
validationSchema={TimeItemsSchema}
onSubmit={(values) => console.log(values)}>
{({ values, errors, touched }) => (
<Form onChange={() => console.log("hs")}>
<FieldArray
name="timeItems"
render={arrayHelpers => (
<div>
{values.timeItems && values.timeItems.length > 0 ? (
values.timeItems.map((timeItem, index) => (
<React.Fragment key={index}>
<Stack gap={2}>
<Flex alignItems="end" gap={4}>
<FormControl>
<FormLabel htmlFor="timeItems[${index}].name">Name</FormLabel>
<Field as={Input} placeholder="Time Item Name" variant="filled" name={`timeItems[${index}].name`} />
</FormControl>
<FormControl>
<FormLabel htmlFor="timeItems[${index}].time">Time</FormLabel>
<InputGroup>
<Field as={Input} type="number" placeholder="0 Hours" variant="filled" name={`timeItems[${index}].time`} />
<InputRightAddon children='Hours' />
</InputGroup>
</FormControl>
<FormControl>
<FormLabel htmlFor="timeItems[${index}].rate">Rate</FormLabel>
<InputGroup>
<Field as={Input} type="number" placeholder="USD 0" variant="filled" name={`timeItems[${index}].rate`} />
<InputRightAddon children='Hours' />
</InputGroup>
</FormControl>
<Flex flexShrink="0" gap={3} direction="column">
<Heading fontWeight="normal" size="sm">Apply Taxes & Discounts</Heading>
<Flex mb={0.5} gap={4}>
<Tooltip label='Tax 1' fontSize='sm'>
<IconButton variant={true ? 'solid' : 'outline'} aria-label='Tax' icon={<TbReceipt />} />
</Tooltip>
<IconButton variant='outline' aria-label='Discount' icon={<TbDiscount />} onClick={() => arrayHelpers.insert(index, { name: "", email: "" })} />
</Flex>
</Flex>
</Flex>
<Flex py={2} gap={10} justifyContent="space-between">
<TimeItemsTable timeItemIndex={index} jiraTimeImported={jiraTimeImported} />
<Flex gap={4}>
<IconButton aria-label='Create Time Item' icon={<MinusIcon />} onClick={() => arrayHelpers.remove(index)} />
<IconButton aria-label='Create Time Item' icon={<AddIcon />} onClick={() => arrayHelpers.insert(index, { name: "", email: "" })} />
</Flex>
</Flex>
</Stack>
<Divider my={4} />
</React.Fragment>
))
) : (
<button type="button" onClick={() => arrayHelpers.push('')}>
Add a Time Item
</button>
)}
<Flex mt={6} gap={10} justifyContent="space-between">
<Button colorScheme="purple" type="submit">Save</Button>
{/* <TimeItemsStats /> */}
</Flex>
</div>
)}
/>
</Form>
)}
</Formik>
</>
)
}
Solution:
The arrayHelpers.push and arrayHelpers.insert didn't insert the values with the correct type, as seen in the code.

How to map transition in mui?

I want to map my products in mui and put each one in Grow, but with this error Warning: Failed prop type: Invalid prop children of type array supplied to ForwardRef(Grow), expect a single ReactElement . I will be
what should i do
if (enter) {
return (
<Box
sx={{
display: "grid",
gridTemplateColumns: "repeat(auto-fit, 250px)",
gap: "10px",
alignItems: "center",
justifyContent: "space-evenly",
padding: "0 50px",
height: "100%",
}}
>
{searchState.length ? (
<>
<Grow in={true}>
{searchState.map((item) => (
<Product key={item.id} productData={item} />
))}
</Grow>
<Grow
in={true}
style={{ transformOrigin: "0 0 0" }}
{...(true ? { timeout: 1000 } : {})}
>
{searchState.map((item) => (
<Product key={item.id} productData={item} />
))}
</Grow>
</>
) : (
<Box sx={{stylesNone}>No products found</Box>
)}
</Box>
);
}
You can wrap your mapped components with a div or fragment (<></>)
<Grow in={true}>
<>
{searchState.map((item) => (
<Product key={item.id} productData={item} />
))}
</>
</Grow>

How to declare one button in a react component and update the title of it in another?

I was wondering if anyone could tell me the best way to dyamically change the button title I'm using in the PopUp component to change the title to 'login' or 'signup' depending on what component I'm passing into the NavBar?
I'm returning a and form into each PopUp component in the navbar as children but have gotten a bit stuck on how to get the title to change. Any help would be much appreciated.
const BootstrapDialog = styled(Dialog)(({ theme }) => ({
"& .MuiDialogContent-root": {
padding: theme.spacing(2),
},
"& .MuiDialogActions-root": {
padding: theme.spacing(1),
},
}));
const BootstrapDialogTitle = (props) => {
const { children, onClose, ...other } = props;
return (
<DialogTitle sx={{ m: 0, p: 2 }} {...other}>
{children}
{onClose ? (
<IconButton
aria-label="close"
onClick={onClose}
sx={{
position: "absolute",
right: 8,
top: 8,
color: (theme) => theme.palette.grey[500],
}}
>
<CloseIcon />
</IconButton>
) : null}
</DialogTitle>
);
};
BootstrapDialogTitle.propTypes = {
children: PropTypes.node,
onClose: PropTypes.func.isRequired,
};
export function PopUp(props) {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button color="inherit" onClick={handleClickOpen}>
SignUp
</Button>
<BootstrapDialog
onClose={handleClose}
aria-labelledby="customized-dialog-title"
open={open}
>
<BootstrapDialogTitle
id="customized-dialog-title"
onClose={handleClose}
>
<Logo />
</BootstrapDialogTitle>
<DialogContent dividers>{props.children}</DialogContent>
</BootstrapDialog>
</div>
);
}
export default function NavBar() {
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="fixed">
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
<Logo />
</Typography>
<PopUp>
<Login />
</PopUp>
<PopUp>
<SignUp />
</PopUp>
<Button color="inherit">About</Button>
</Toolbar>
</AppBar>
</Box>
);
}

How change background of an dynamic array list when a city is selected

<div className="images-container">
{cities?.map((city) => (
<>
{city?.isActive && (
<>
{city?.images.map((image) => (
<div className="img-block">
<img className="cardd-img" src={image.image} alt="DGNet" />
<p className="paragrafo">{image?.paragraph}</p>
</div>
))}
</>
)}
</>
))}
</div>
I have a list os cities and I need to change the background when a city os selected, here is what i have
const [cities, setCities] = useState([
{
name: "Divinópolis",
isActive: false,
images: [
{
image: imgLogoTIVerde,
paragraph: "Special Sales e Technical Support",
}
],
},
{
name: "Nova Olímpia",
isActive: false,
images: [
{
image: imgLogoLivitech,
paragraph: "Special Sales e Technical Support",
}
],
},
const states = [
{
name: 'minas gerais',
cities: ['Divinópolis', '']
},
{
name: 'paraná',
cities: ['Nova Olímpia', '']
}
]
function handleChangeCity(name) {
const cityChanged = cities.map((city) => {
city.isActive = false;
if (city.name === name) city.isActive = true;
if (city.name === name) city.arrowActive = true;
return city;
});
setCities(cityChanged);
}
<div className="scroll">
{states?.map(state => (
<div key={state.name} className="cidade">
<header className="header">
<h1 className="font-bold">{state.name}</h1>
</header>
{state.cities.map(city => (
<>
<div className="city-block">
<label className="label" for="content">
{city}
</label>
<input type="radio" name="radio" className="single" onClick={() => handleChangeCity(city)} />
</div>
</>
))}
</div>
))}
</div>
At the moment when I select a city an img shows on a container, that works fine, what really need is that the background of that city div change as well, but only the celected one.
I added the code part where it shows the image when the city is selected, each city may have a different image or the same as the others
It wasn't 100% clear what div you wanted to add the background color to, but this logic should work for you.
{state.cities.map(city => (
<>
<div className="city-block" style={{ backgroundColor: city.isActive ? 'blue' : 'none' }}>
<label className="label" for="content">
{city}
</label>
<input type="radio" name="radio" className="single" onClick={() => handleChangeCity(city)} />
</div>
</>
))}
You can pass different className if isActive or not, or use the style props. Example:
<div className={city.isActive ? 'class-with-backgroud-1' : 'class-with-backgroud-2'}>
...
</div>
or:
<div style={{ backgroundColor: city.isActive ? 'color-1' : 'color-2' }}>
...
</div>

Reactjs TypeError: Cannot read property 'id' of undefined

I facing problem "TypeError: Cannot read property 'id' of undefined" when i using Grid in elements.
the error i facing like this.
Here is my sample code.
In this code only i am facing the issue when im using Grid
<ThemeProvider theme={theme}>
<Card>
<Edit {...props}>
<SimpleForm>
<Grid container spacing={1} align="center">
<Grid item sm={6}>
<ReferenceInput
source="appId"
reference="_apps"
allowEmpty
defaultValue={
props.location.data ? props.location.data.appId : ""
}
validate={required()}
>
<SelectInput optionText="label" />
</ReferenceInput>
</Grid>
<Grid item sm={6}>
<SelectInput
source="iconColor"
choices={[
{ id: "primary", name: "primary" },
{ id: "secondary", name: "secondary" },
{ id: "action", name: "action" },
{ id: "disabled", name: "disabled" },
]}
/>
</Grid>
<Grid item sm={6}>
<ReferenceManyField
label={"resources._fields.name"}
reference="_fields"
target="eid"
>
<Datagrid>
<TextInput type="text" source="label" />
<TextInput type="text" source="component" />
<BooleanField source="showInList" />
<BooleanField source="showInFilter" />
<BooleanField source="showInCreate" />
<BooleanField source="showInEdit" />
<BooleanField source="showInShow" />
<EditButton />
</Datagrid>
</ReferenceManyField>
</Grid>
<Grid item sm={6}>
<ReferenceManyField
label={"resources._triggers.name"}
reference="_triggers"
target="eid"
>
<Datagrid>
<TextInput type="text" source="name" />
<BooleanField source="beforeInsert" />
<BooleanField source="afterInsert" />
<BooleanField source="beforeUpdate" />
<BooleanField source="afterUpdate" />
<BooleanField source="beforeDelete" />
<BooleanField source="afterDelete" />
<EditButton />
</Datagrid>
</ReferenceManyField>
</Grid>
<Grid item sm={6}>
<AddTriggerButton />
<AddFieldButton />
</Grid>
</Grid>
</SimpleForm>
</Edit>
</Card>
</ThemeProvider>
This is my actual code in that screenshot:
const TriggerButton = ({ children, to, ...props }) => {
const CustomLink = React.useMemo(
() =>
React.forwardRef((linkProps, ref) => (
<StyledLink ref={ref} to={to} {...linkProps} />
)),
[to]
);
return (
<Button {...props} component={CustomLink}>
{children}
</Button>
);
};
export default class AddTriggerButton extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false,
props: props,
};
}
render() {
return (
<div>
<TriggerButton
component={Link}
to={{
pathname: "/_triggers/create",
data: { eid: this.state.props.record.id },
}}
startIcon={<AddIcon />}
>
New Trigger
</TriggerButton>
</div>
);
}
}
Because you don't pass any props to AddTriggerButton so props is {}. So this.state.props is {} and this.state.props.record become undefined.
This is not good logic. You need to pass props and use this.props instead this.state.props
<AddTriggerButton record={{id: value}} />
Change this.state.props.record.id to this.props.record.id
Try to console.log(this.state.props.record.id) and shate here the reault. How you defined your the props? Maybe there is an asynchronous problem, so try to put '?' before the id like this:
this.state.props.record?.id

Categories

Resources