how show input only if checkbox is cheked? Reac | next.js - javascript

I try to manage this task but I don’t understand how should I do.
I want to show the promo code field only if the checkbox(I have promo code) is checked.
Also, it would be great to show this field use js method, not CSS style display:none
Please help if you have any idea
Maybe it should be simle function with if else?
import React from "react";
import { useState } from "react";
import { Box, Button, chakra, Link, Stack, VStack } from "#chakra-ui/react";
import { Heading } from "#/components/shared/Heading";
import { FieldError, useForm } from "react-hook-form";
import FormInput from "#/components/base/form/FormInput";
import FormRadioCard from "#/components/base/form/FormRadioCard";
import NextLink from "next/link";
import composeValidations, {
validations,
} from "../../base/form/validations/formValidations";
import FormCheckbox from "#/components/base/form/FormCheckbox";
import { UseFormRegisterReturn } from "react-hook-form/dist/types/form";
import { LeadFormAnswers } from "#/components/lead-form/form/useLeadForm";
import IncentiveBubble from "#/components/base/IncentiveBubble";
import FormPhoneNumber from "#/components/base/form/FormPhoneNumber";
const LINK_SEPARATOR = "{{link}}";
const PrivacyPolicyCheckbox: React.FC<PrivacyPolicyCheckboxProps> = ({
registerProps,
link,
error,
text,
}) => {
const sentenceParts = text.split(LINK_SEPARATOR);
const firstPart = sentenceParts[0];
const secondPart = sentenceParts[1];
return (
<FormCheckbox
error={error}
registerProps={registerProps}
px={[5, 8]}
mt={6}
>
{firstPart}
<NextLink href={link.href} passHref>
<Link color="blue.400" target="_blank">
{link.title}
</Link>
</NextLink>
{secondPart}
</FormCheckbox>
);
};
const emailValidation = composeValidations(
validations.requiredEmail,
validations.rejectForbiddenDomains,
validations.rejectDisposableEmails
);
const Row: React.FC = ({ children }) => (
<Stack gap={6} w="full" direction={["column", "row"]}>
{children}
</Stack>
);
const EmbeddedRow: React.FC<{ embedded?: boolean }> = ({
children,
embedded,
}) => {
if (embedded) {
return <Row>{children}</Row>;
}
return <>{children}</>;
};
const LeadFormFirstPage: React.VFC<LeadFormFirstPageProps> = ({
onSubmit,
embedded,
title,
emailLabel,
emailForbiddenDomainErrorLink,
numberOfEmployeesLabel,
numberOfEmployeesOptions,
privacyPolicyText,
privacyPolicyLink,
submitText,
bubbleText,
promoCodeText,
promoCodeLabel,
}) => {
const {
register,
formState: { errors },
handleSubmit,
control,
setValue,
} = useForm<LeadFormAnswers>();
return (
<Box>
<Heading px={[5, 8]} level={3} mb={8} fontWeight={600}>
{title}
</Heading>
<Box
as={chakra.form}
onSubmit={handleSubmit((data) => {
if (!embedded) {
window.scrollTo({ top: 0 });
}
onSubmit(data);
})}
>
<VStack gap={6} alignItems="flex-start" px={[5, 8]}>
<EmbeddedRow embedded={embedded}>
<FormInput
w="full"
label={emailLabel}
error={errors.email}
errorParams={{ link: emailForbiddenDomainErrorLink }}
registerProps={register("email", emailValidation)}
/>
</EmbeddedRow>
</VStack>
<FormRadioCard
label={numberOfEmployeesLabel}
name="numberOfEmployees"
control={control}
options={numberOfEmployeesOptions}
/>
<PrivacyPolicyCheckbox
error={errors.consent}
registerProps={register("consent", validations.required)}
text={privacyPolicyText}
link={privacyPolicyLink}
/>
<VStack gap={6} alignItems="flex-start" px={[5, 8]}>
<FormCheckbox
mt={6}
label={promoCodeText}
registerProps={register("checkbox")}
>
{promoCodeText}
</FormCheckbox>
<Row>
<FormInput
w="full"
label={promoCodeLabel}
registerProps={register("promoCode")}
/>
</Row>
</VStack>
<IncentiveBubble
text={bubbleText}
variant="transparent"
mt={[6, 10]}
px={[5, 8]}
>
<Button variant="primary" size="M" type="submit">
{submitText}
</Button>
</IncentiveBubble>
</Box>
</Box>
);
};
type LinkProps = { title: string; href: string };
export type LeadFormFirstPageProps = {
onSubmit(data: LeadFormAnswers): void;
embedded?: boolean;
title: string;
emailLabel: string;
emailForbiddenDomainErrorLink: string;
numberOfEmployeesLabel: string;
numberOfEmployeesOptions: string[];
privacyPolicyText: PrivacyPolicyCheckboxProps["text"];
privacyPolicyLink: PrivacyPolicyCheckboxProps["link"];
submitText: string;
bubbleText: string;
promoCodeText: string;
promoCodeLabel: string;
};
export default LeadFormFirstPage;

Here is a simple approach where we have the checkbox then the text input field of the promo code. We use the checked value of the checkbox to show/hide the promo code field.
import React, { useState } from "react";
export default function CheckBoxExample() {
// checked state and the onChange method
const [hasPromo, setHasPromo] = useState(false);
const onChangeCheckBox = (e) => {
setHasPromo(e.target.checked);
};
// the promo code input field value and the onChange method
const [promo, setPromo] = useState("");
const onChangePromo = (e) => {
setPromo(e.target.value);
};
return (
<div>
<form>
<input type="checkbox" checked={hasPromo} onChange={onChangeCheckBox} />
{hasPromo && (
<input type="text" value={promo} onChange={onChangePromo} />
)}
</form>
</div>
);
}

hope this example helps you understanding how to toggle a state of an element with useState :
import { useState } from "react";
export default function App() {
const [isChecked, setIsChecked] = useState(false);
return (
<div className="App">
<input
type="checkbox"
defaultChecked={isChecked}
onClick={() => setIsChecked(!isChecked)}
/>
{isChecked ? "text is shown" : "text should be hidden"}
</div>
);
}

Related

Create a CommentList component from a json file submissions reactjs

I am trying to implement my own commenting system.
I already set up the comment form and I receive data in my netlify form submissions.
Then, I use the plugin netlify-plugin-form-submissions, which transforms your netlify form submissions into a json file (in my case in Form submissions data saved: static/comments/approved-comments_submissions.json)
So I am trying to retrieve the submissions data and make them appear as a comment list below my form.
Here is my CommentList Component:
import React, { useReducer } from 'react';
import "./styles.module.css";
class CommentsList extends React.Component {
constructor(props) {
super(props);
this.state = {
commentList: "../../static/comments/approved-comments_submissions.json"
}
}
renderComments() {
return this.state.commentList.map((item, index) => (
<ul>
<li>
<p>{item.data.name} a commenté le {item.created_on}</p>
<p>{item.data.commentaire}</p>
</li>
</ul>
));
}
render() {
return (
<div className="CommentsList">
{this.renderComments()}
</div>
);
}
}
export default CommentsList;
however it does not work, I can't retrieve the data from approved-comments_submissions. I have the following error:
TypeError: this.state.commentList.map is not a function
Besides, how can I render the comments only in the right urlpage? Because comments need to appear only in the right page
Here is an exemple of the data submission json file
[{"number":19,"title":null,"email":"email#email","name":"firstname", "summary":"testing","body":"testing","data":{"urlpage":"https://blabla.com/the/right/page/","name":"firstname","email":"email#email","commentaire":"testing"},"ip":"1.1.1.1","created_at":"2022-03-21T14:55:57.736Z","id":"aaaaaaaaa","form_id":"bbbbbbbb","site_url":"https://blabla.com","form_name":"approved-comments"}]
Here is my CommentForm code.
import React, { useReducer } from 'react';
import { makeStyles } from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
import { NetlifyForm, Honeypot } from 'react-netlify-forms'
import { useState } from "react"
import { useNetlifyForm, NetlifyFormProvider, NetlifyFormComponent} from "react-netlify-forms"
import { useFormik } from 'formik'
import { useLocation } from 'react-router-dom'
import "./styles.module.css";
const useStyles = makeStyles(theme => ({
input: {
minHeight: 100,
},
}));
const Commentbox = () => {
const classes = useStyles();
const netlify = useNetlifyForm({
name: 'approved-comments',
action: '/',
honeypotName: 'bot-field',
onSuccess: (response, context) => {
console.log('Successfully sent form data to Netlify Server')
}
})
const [touched, setTouched] = useState(false);
const location = useLocation();
const handleTouch = () => {
setTouched(true);
};
const {
handleSubmit,
handleChange,
handleBlur,
errors,
values
} = useFormik({
initialValues: { name: '', email: '', commentaire: '', urlpage: '' },
onSubmit: (values, {setStatus, resetForm}) => {
values.urlpage = "https://blabla.com" + location.pathname
netlify.handleSubmit(null, values);
resetForm();
setStatus({success: true});
},
validate: (values) => {
const errors = {}
if (
!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
) {
errors.email = 'Adresse email invalide'
}
return errors
}
})
return (
<NetlifyFormProvider {...netlify}>
<input type="hidden" name="form-name" value="approved-comments" />
<h3>Leave a comment 😃</h3>
<NetlifyFormComponent onSubmit={handleSubmit}>
<Honeypot />
{netlify.success && (
<p sx={{ variant: 'alerts.success', p: 3 }}>
Thx for your comment 😃
</p>
)}
{netlify.error && (
<p sx={{ variant: 'alerts.muted', p: 3 }}>
Sorry 😢.
</p>
)}
<input
type="hidden"
name="urlpage"
id="urlpage"
/>
<TextField
required
id="name"
name='name'
label="Nom"
variant="outlined"
fullWidth
margin="normal"
onChange={handleChange}
onBlur={handleBlur}
error={errors.name}
value={values.name}
style = {{width: "70%"}}
/>
<TextField
required
id="email"
name='email'
label="Email"
variant="outlined"
fullWidth
margin="normal"
onChange={handleChange}
onBlur={handleBlur}
onFocus={handleTouch}
error={errors.email}
helperText={touched && !/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email) ? 'Adresse email non valide' : ' '}
value={values.email}
style = {{width: "70%"}}
/>
<TextField
id="commentaire"
name='commentaire'
label="Commentaire"
variant="outlined"
fullWidth
margin="normal"
multiline
onChange={handleChange}
onBlur={handleBlur}
error={errors.commentaire}
value={values.commentaire}
inputProps={{
className: classes.input
}}
style = {{width: "70%"}}
/>
{/* <input type='hidden' name='name' value='values.name' />
<input type='hidden' name='email' value='values.email' />
<input type='hidden' name='commentaire' value='values.commentaire' /> */}
<button class="button button--lg button--primary" type="submit">
Publiez votre commentaire
</button>
</NetlifyFormComponent>
</NetlifyFormProvider>
)
}
export default Commentbox;
EDIT
So now my code compiles
import React, { useReducer } from 'react';
import "./styles.module.css";
import commentList from '../../../static/comments/approved-comments_submissions.json'
const Comments = commentList.map((item) => {
<ul>
<li>
<p>{item.data.name} a commenté le {item.created_on}</p>
<p>{item.data.commentaire}</p>
</li>
</ul>
} )
class CommentsList extends React.Component {
render() {
return (
<div>
{Comments}
</div>
);
}
}
export default CommentsList;
however comments are still not rendering below my comment form :/

Error when passing props with Ionic/React/Typescript - Wrong props in React.FC<'wrong props here'>

After dealing with this problem for good while I got no success. I have been checking many questions around here but I could not find one that suits my case, so please, I would like to ask you for help.
I have a problem passing my props through the <WeatherCard/> component. The test application has 2 tabs and both tabs have the <WeatherCard/> being rendered.
When I hover <WeatherCard/> in Tab1.tsx Typescript shows me the wrong (unexpected) props (WeatherProps), see below:
(alias) const WeatherCard: React.FC<WeatherProps>
import WeatherCard
On the other hand, whereas when I hover <WeatherCard/> in Tab2.tsx it shows the correct props being passed, see below:
(alias) const WeatherCard: React.FC<WeatherCardProps>
import WeatherCard
Moreover it shows the following error:
[react-scripts] TS2322: Type '{ weatherIconUrl: string; weatherData: any; weatherVars: string[]; }' is not assignable to type 'IntrinsicAttributes & WeatherProps & { children?: ReactNode; }'.
[react-scripts] Property 'weatherIconUrl' does not exist on type 'IntrinsicAttributes & WeatherProps & { children?: ReactNode; }'.
I console.log the props passed in <WeatherProperty/> and these props are actually the props passed to <WeatherCard/> so, it seems like for some reason the props declared in
<WeatherProperty/> are not taken into account when using Tab1
I will include the code below:
Tab1.tsx
import {
IonButton,
IonButtons,
IonCard,
IonCardContent,
IonCol,
IonContent,
IonGrid,
IonHeader,
IonItem,
IonPage,
IonRow,
IonText,
IonThumbnail,
IonTitle,
IonToolbar,
IonLoading,
IonAlert,
} from "#ionic/react";
import styles from "./Tab1.module.css";
import { RefreshOutline } from "react-ionicons";
import { Geolocation } from "#capacitor/geolocation";
import React, { useEffect } from "react";
import { RootState } from "../app/store";
import { useDispatch, useSelector } from "react-redux";
import { useGetCurrentPositionWeatherQuery } from "../services/weather";
import { setQueryCoord } from "../app/coordQuerySlice";
import TestSkeleton from "../components/TestSkeleton";
import WeatherCard from "../components/WeatherProperty";
const Tab1: React.FC = () => {
const dispatch = useDispatch();
const coordQueryState = useSelector((state: RootState) => state.coordQuery);
const {
refetch,
data: weatherData,
isFetching,
isError,
} = useGetCurrentPositionWeatherQuery(
{
lat: coordQueryState.lat,
lon: coordQueryState.lon,
appid: "cd555b96865912ac5781d36d6d7de140",
units: "metric",
},
{ skip: coordQueryState.skip }
);
const setCurrentPosition = async () => {
const data = await Geolocation.getCurrentPosition();
const {
coords: { latitude: latFetched },
coords: { longitude: lonFetched },
} = data;
dispatch(setQueryCoord({ lat: latFetched, lon: lonFetched, skip: false }));
};
useEffect(() => {
setCurrentPosition();
}, []);
function refreshCurrentPositionHandler() {
refetch();
}
if (weatherData) {
console.log(weatherData);
}
const weatherIconUrl = weatherData
? `https://openweathermap.org/img/wn/${weatherData.weather[0].icon}#2x.png`
: undefined;
const weatherVars = weatherData ? Object.keys(weatherData.main) : undefined;
return (
<IonPage>
<IonHeader>
<IonToolbar className={styles["ion-toolbar-dashboard"]}>
<IonTitle className="ion-margin-bottom" size="large">
Dashboard
</IonTitle>
<IonButtons slot="end">
<IonButton>
<RefreshOutline
onClick={refreshCurrentPositionHandler}
color={"black"}
height="35px"
width="35px"
cssClasses={styles.refreshOutline}
/>
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonGrid className="ion-no-margin">
<IonRow style={{ margin: "10px" }}>
<IonCol className="ion-text-center">
<h1 style={{ fontSize: "20px" }}>
Here's your location based weather
</h1>
</IonCol>
</IonRow>
</IonGrid>
{!weatherData && <IonLoading isOpen={!weatherData} />}
{isFetching && !weatherData && <IonLoading isOpen={isFetching} />}
{isError && <IonAlert isOpen={isError} />}
{!isFetching && weatherData && (
<WeatherCard
weatherIconUrl={weatherIconUrl as string} \\problem is indeed here
weatherData={weatherData}
weatherVars={weatherVars as string[]}
/>
)}
</IonContent>
</IonPage>
);
};
export default Tab1;
Tab2.tsx
import {
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
} from "#ionic/react";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { setQueryCity } from "../app/cityQuerySlice";
import { RootState } from "../app/store";
import WeatherCard from "../components/WeatherCard";
import { useGetWeatherByCityQuery } from "../services/weather";
import styles from "./Tab1.module.css";
const Tab2: React.FC = () => {
const dispatch = useDispatch();
const cityQueryState = useSelector((state: RootState) => state.cityQuery);
const {
refetch,
data: weatherData,
isFetching,
isError,
} = useGetWeatherByCityQuery(
{
q: cityQueryState.city,
appid: "cd555b96865912ac5781d36d6d7de140",
units: "metric",
},
{ skip: cityQueryState.skip }
);
useEffect(() => {
dispatch(setQueryCity({ city: "London", skip: false }));
}, [dispatch]);
const weatherIconUrl = weatherData
? `https://openweathermap.org/img/wn/${weatherData.weather[0].icon}#2x.png`
: undefined;
const weatherVars = weatherData ? Object.keys(weatherData.main) : undefined;
return (
<IonPage>
<IonHeader>
<IonToolbar className={styles["ion-toolbar-dashboard"]}>
<IonTitle className="ion-margin-bottom" size="large">
Search
</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
{!weatherData && <p>weather data is loading</p>}
{weatherData && (
<WeatherCard
weatherData={weatherData} \\ and here the props are passed properly...
weatherIconUrl={weatherIconUrl as string}
weatherVars={weatherVars as string[]}
/>
)}
</IonContent>
</IonPage>
);
};
export default Tab2;
WeatherCard.tsx
import {
IonCard,
IonCardContent,
IonGrid,
IonRow,
IonCol,
IonText,
} from "#ionic/react";
import { useEffect } from "react";
import WeatherProperty from "./WeatherProperty";
interface WeatherCardProps {
weatherIconUrl: string;
weatherVars: string[];
weatherData: any;
}
const WeatherCard: React.FC<WeatherCardProps> = (props: WeatherCardProps) => {
const { weatherVars, weatherData, weatherIconUrl } = props;
console.log(weatherData);
console.log(weatherData);
console.log(weatherIconUrl);
useEffect(() => {
console.log("component WeatherCard mounted");
});
return (
<IonCard>
<IonCardContent>
<IonGrid>
<IonRow>
<IonCol class="ion-text-center">
<IonText color="primary">
<h1 style={{ marginBottom: "0px", display: "inline" }}>
{weatherData.name},
<span style={{ color: "grey" }}>
{" "}
{weatherData.sys.country === "JP"
? "Japan"
: "Outside Japan"}
</span>
</h1>
</IonText>
</IonCol>
</IonRow>
<IonRow className="ion-justify-content-center ion-align-items-center">
<IonCol size="auto">
<img
style={{
width: "70px",
height: "70px",
display: "inline",
}}
src={weatherIconUrl}
/>
</IonCol>
<IonCol size="auto" className="ion-justify-content-center">
<h1
style={{
display: "inline",
fontSize: "18px",
}}
>
{weatherData.weather[0].description}
</h1>
</IonCol>
</IonRow>
<IonRow>
<IonCol>
<WeatherProperty
main={weatherVars[1]}
mainValue={weatherData.main[weatherVars[1]]}
/>
</IonCol>
<IonCol>
<WeatherProperty
main={weatherVars[2]}
mainValue={weatherData.main[weatherVars[2]]}
/>
</IonCol>
</IonRow>
<IonRow>
<IonCol>
<WeatherProperty
main={weatherVars[3]}
mainValue={weatherData.main[weatherVars[3]]}
/>
</IonCol>
<IonCol>
<WeatherProperty
main={weatherVars[5]}
mainValue={weatherData.main[weatherVars[5]]}
/>
</IonCol>
</IonRow>
</IonGrid>
</IonCardContent>
</IonCard>
);
};
export default WeatherCard;
WeatherProperty.tsx
import { IonItem, IonLabel, IonText, IonThumbnail } from "#ionic/react";
import { useEffect } from "react";
import "./WeatherProperty.module.css";
interface WeatherProps {
main: string;
mainValue: number;
}
const WeatherProperty: React.FC<WeatherProps> = (props: WeatherProps) => {
console.log(`these are the props in WeatherProperty component`);
console.log(props);
let propMod;
let unit;
let fileName;
if (props.main === "feels_like") {
propMod = "It feels like:";
unit = "deg";
fileName = "feels-like.png";
}
if (props.main === "temp_min") {
propMod = "Minimum temperature:";
unit = "deg";
fileName = "temp-min.png";
}
if (props.main === "temp_max") {
propMod = "Maximum temperature:";
unit = "deg";
fileName = "temp-max.png";
}
if (props.main === "humidity") {
propMod = "Humidity:";
unit = "%";
fileName = "humidity.png";
}
useEffect(() => {
console.log("component WeatherProperty mounted");
});
return (
<IonItem lines="none">
<IonThumbnail slot="start" className="weather-icons">
<img src={`${window.location.origin}/assets/${fileName}`} />
</IonThumbnail>
<IonLabel slot="">
<IonText color="primary">
<h1 style={{ fontSize: "15px" }}>{propMod}</h1>
</IonText>
<h2>{`${Math.trunc(props.mainValue)} ${unit}`}</h2>
</IonLabel>
</IonItem>
);
};
export default WeatherProperty;
There are two things you need to fix:
Imported from the wrong component
Tab1.tsx
import WeatherCard from "../components/WeatherProperty";
// Maybe the correct one is "WeatherCard" ?
// import WeatherCard from "../components/WeatherCard";
Assigned the wrong type definition for props
WeatherCard.tsx
const WeatherProperty: React.FC<WeatherProps> = (props: WeatherProps) => {
// you can just omit the prop's type
// (props) => {
//
// or use object destructuring for the convenience
// ({ weatherData, weatherVar, weatherIconUrl }) => {

Form validation with conditional fields using yup

I am trying to conditional render the fields and submit the data.
But on the below code snippet, i am not able to achieve this. Issues are re rendering happens and the values not getting persisting.
Here mostly the problem is i am splitting the schema, so based on the selection of the choice the field renders.
How can i submit the data with proper persisting the validation and values.
What i have tried so far
App.js
import React, { useEffect, useState } from "react";
import "./styles.css";
import Select from "react-select";
import { Controller, useForm } from "react-hook-form";
import { yupResolver } from "#hookform/resolvers";
import { CITIZEN_OPTIONS, validationSchema } from "./util";
import { Resident, NonResident } from "./CitizenDetails";
const Fallback = () => null;
export default function App() {
const [citizenValue, setCitizenValue] = useState(null);
const { register, control, errors, watch, handleSubmit } = useForm({
resolver: yupResolver(validationSchema),
mode: "onBlur",
reValidateMode: "onChange"
});
const watchCitizen = watch("citizen");
useEffect(() => {
setCitizenValue(watchCitizen?.value);
}, [watchCitizen]);
const citizenDetails = {
resident: () => <Resident errors={errors} register={register} />,
non_resident: () => (
<NonResident errors={errors} control={control} register={register} />
)
};
const onSubmit = (data) => {
console.log(data);
};
const SelectedCitizenFields = citizenDetails[citizenValue] || Fallback;
return (
<div className="App">
<Controller
as={Select}
control={control}
name="citizen"
options={CITIZEN_OPTIONS}
></Controller>
<SelectedCitizenFields />
<button onClick={handleSubmit(onSubmit)}>Submit Details</button>
</div>
);
}
CitizenDetails.js
import React, { Fragment, memo } from "react";
import { Controller } from "react-hook-form";
import Select from "react-select";
export const Resident = memo((props) => {
const { errors, register } = props;
return (
<Fragment>
<div className="field-group">
<label>Enter first name</label>
<input ref={register} name="first_name"></input>
{errors?.first_name?.message && (
<span>{errors.first_name.message}</span>
)}
</div>
<div className="field-group">
<label>Enter last name</label>
<input ref={register} name="last_name"></input>
{errors?.last_name?.message && <span>{errors.last_name.message}</span>}
</div>
</Fragment>
);
});
export const NonResident = memo((props) => {
const { errors, register, control } = props;
return (
<Fragment>
<div className="field-group">
<label>Enter passport number</label>
<input ref={register} name="passport_number"></input>
{errors?.passport_number?.message && (
<span>{errors.passport_number.message}</span>
)}
</div>
<div className="field-group">
<label>Choose Country</label>
<Controller as={Select} control={control} name="country" options={[]} />
{errors?.country?.message && <span>{errors.country.message}</span>}
</div>
<div className="field-group">
<label>Choose State</label>
<Controller as={Select} control={control} name="state" options={[]} />
{errors?.state?.message && <span>{errors.state.message}</span>}
</div>
</Fragment>
);
});
util.js
import { object, string, number, lazy } from "yup";
export const CITIZEN_OPTIONS = [
{
label: "Resident",
value: "resident"
},
{
label: "Non-Resident",
value: "non_resident"
}
];
const required = () => "field is required";
const resident_schema = object({
first_name: string().required(required).nullable(),
last_name: string().required(required).nullable()
});
const non_resident_schema = object({
passport_number: string().required(required).nullable(),
country: object().required(required).nullable(),
state: object().required(required).nullable()
});
export const validationSchema = lazy(({ citizen }) => {
return citizen?.value === "resident" ? resident_schema : non_resident_schema;
});
Here is the codesandbox link

Value on Object is null when sending from axios to API Controller.How to solve it?

I am making React Crud Application and when try to send data from axios to API Controller I am not able to send those data, while checking in API I found that all the the values are null. But with the same API and values i tried from POSTMAN it worked perfectly. How Can i solve this?
import React, { FormEvent, useState } from 'react'
import { Segment, Grid, GridColumn, Button, Form, Container } from 'semantic-ui-react'
import { IEmployee } from '../Model/activity'
import { RouteComponentProps } from 'react-router-dom'
import axios from 'axios';
import {v4 as uuid} from 'uuid';
interface DetailParams {
id: string;
}
const EmployeeForm : React.FC<RouteComponentProps<DetailParams>> = ({ match, history }) => {
const [employee, setEmployee] = useState<IEmployee>({
id: '',
firstName: '',
lastName: '',
address: '',
organization: ''
})
const handleInputChange = (event: FormEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = event.currentTarget;
setEmployee({ ...employee, [name]: value })
}
const handleSubmit = () => {
console.log(employee);
if (employee.id.length === 0) {
let newActivity = {
...employee,
id: uuid(),
}
console.log(employee);
axios.post('https://localhost:44353/Employee/CreateEmployee',{data : employee})
.then((response) => {
history.push(`/manage/${newActivity.id}`)
})
} else {
axios.post('https://localhost:44353/Employee/EditEmployee',{data : employee})
.then((response) => {
history.push(`/manage/${employee.id}`)
})
}
}
return (
<Container style={{ marginTop: '7em' }}>
<Grid>
<GridColumn width={10}>
<Segment clearing>
<Form onSubmit={handleSubmit}>
<Form.Input name='firstName' onChange={handleInputChange} placeholder='First Name' value={employee.firstName} />
<Form.TextArea name='lastName' onChange={handleInputChange} placeholder='Last Name' value={employee.lastName} />
<Form.Input name='address' onChange={handleInputChange} placeholder='Address' value={employee.address} />
<Form.Input name='organization' onChange={handleInputChange} placeholder='Organization' value={employee.organization} />
<Button floated='right' positive type='submit' content='Submit' />
<Button onClick={() => history.push('/employeeList')} floated='right' type='button' content='Cancel' />
</Form>
</Segment>
</GridColumn>
</Grid>
</Container>
)
}
export default EmployeeForm
The above is my form class from where the data is to be send from axios.
While Console.log in handle submit button the values are displayed perfectly.
My NET.Core API is :-
[HttpPost]
public async Task<ActionResult> CreateEmployee([FromBody] Employee Employee)
{
var result = await _employeeService.CreateEmployee(Employee);
return Ok(Employee.FirstName);
}
It was wrong with syntax. when chane changed axios.post('https://localhost:44353/Employee/CreateEmployee',{data : employee}) to axios.post('https://localhost:44353/Employee/CreateEmployee',employee) it worked fine

How do I access a function that is being updated from a redux store properly?

I have this component that I split for easy management. Before splitting everything worked as expected, after splitting I am getting an error when I click on an icon which calls the createReactionsIcon. Error says
TypeError: updateReaction is not a function
onClick
./components/home/components/SingleUpload.jsx:26
23 |
24 | return icons.map(({ key, text, type }) => (
25 | <IconText
> 26 | onClick={() => updateReaction(item.id, key)}
| ^ 27 | key={key}
28 | type={type}
29 | text={text}
How can I access this correctly from my Home component where updateReaction is returning updateReaction from the redux store.
SubComponent
import PropTypes from 'prop-types';
import React from 'react';
import { Avatar, Card, Icon, List } from 'antd';
import { LIST_TEXTS, STYLES } from '../constants';
const { AVATAR, CARD_CONTAINER, CARD_LIST, ICON, USER_LIST } = STYLES;
const { INNER, MORE, UPLOAD, VERTICAL } = LIST_TEXTS;
const IconText = ({ type, text, onClick }) => (
<span>
<Icon type={type} style={ICON} onClick={onClick} />
{text}
</span>
);
function createReactionsIcon(item, updateReaction) {
const { like, dislike, maybe } = item.reactions;
const icons = [
{ key: 'like', text: `${like.count}`, type: 'heart' },
{ key: 'dislike', text: `${dislike.count}`, type: 'dislike' },
{ key: 'maybe', text: `${maybe.count}`, type: 'meh' },
];
return icons.map(({ key, text, type }) => (
<IconText
onClick={() => updateReaction(item.id, key)}
key={key}
type={type}
text={text}
/>
));
}
export default class SingleUpload extends React.Component {
render() {
const { values } = this.props;
return (
<div style={CARD_CONTAINER}>
<List
itemLayout={VERTICAL}
dataSource={values}
renderItem={item => {
const { avatar, description, id, uploader: { image, name } } = item;
return (
<List.Item style={USER_LIST}>
<Card
actions={createReactionsIcon(item, this.updateReaction)}
cover={<img alt={UPLOAD} src={image} />}
extra={<Icon type={MORE} />}
hoverable
key={id}
title={(
<a href="/">
<Avatar src={avatar} style={AVATAR} />
{name}
</a>
)}
type={INNER}
style={CARD_LIST}
>
{description}
</Card>
</List.Item>
);
}}
/>
</div>
);
}
}
Home.js
import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import SingleUpload from './SingleUpload';
import ComparisonUpload from './ComparisonUpload';
import { STYLES } from '../constants';
import * as actions from '../actions';
import { getUploads } from '../selectors';
const { CARD_CONTAINER } = STYLES;
class Home extends React.Component {
componentDidMount() {
const { actions: { requestUploadList } } = this.props;
requestUploadList();
}
updateReaction = (id, reaction) => {
const { actions: { updateReaction } } = this.props;
const payload = { id, reaction };
updateReaction(payload);
}
render() {
const { uploads } = this.props;
return (
<div style={CARD_CONTAINER}>
<SingleUpload values={[...uploads.values()]} />
<ComparisonUpload values={[...uploads.values()]} />
</div>
);
}
}
Home.propTypes = {
actions: PropTypes.objectOf(PropTypes.object),
uploads: PropTypes.instanceOf(Map),
};
const mapStateToProps = state => ({
uploads: getUploads(state),
});
const mapDispatchToProps = dispatch => ({
actions: bindActionCreators(actions, dispatch),
});
export default connect(mapStateToProps, mapDispatchToProps)(Home);
Pass your function to component as props,
<SingleUpload values={[...uploads.values()]} updateReaction = {this.updateReaction}/>
Now you can use this in your child component,
<IconText onClick={() => this.props.updateReaction(item.id, key)}
You can pass the updateReaction from your parent to child as a callback
<SingleUpload values={[...uploads.values()]} hanldeReaction={this.updateReaction} />
And you can access it in the child using props.hanldeReaction
<Card actions={createReactionsIcon(item, this.props.hanldeReaction)}
You have to pass down the updateReaction() event-handler you defined in Home as a prop to SingleUpload. Then you can access that prop from anywhere inside your component.
Which means we can cleanup the actions prop inside the Card since we only need to pass the item now.
<Card actions={createReactionsIcon(item)}
As well as createReactionsIcon, now we just call that prop directly inside the function
function createReactionsIcon(item) {
const { like, dislike, maybe } = item.reactions;
const icons = [
{ key: 'like', text: `${like.count}`, type: 'heart' },
{ key: 'dislike', text: `${dislike.count}`, type: 'dislike' },
{ key: 'maybe', text: `${maybe.count}`, type: 'meh' },
];
return icons.map(({ key, text, type }) => (
<IconText
onClick={() => this.props.updateReaction(item.id, key)}
key={key}
type={type}
text={text}
/>
));
}
Less redundant code overall which sounds like what you are trying to achieve.

Categories