Arrow Function React Component different from "equivalent" counterpart - javascript

I'm following a tutorial and I am getting confused with my arrow version of it and their function version.
I have a LoaderButton.js and I can write the component as a normal functional component or an arrow component:
Functional Component:
export default function LoaderButton({
isLoading,
className = "",
disabled = false,
...props
}) {
return (
<Button
className={`LoaderButton ${className}`}
disabled={disabled || isLoading}
{...props}
>
{isLoading && <Glyphicon glyph="refresh" className="spinning" />}
{props.children}
</Button>
);
}
Arrow Component:
const LoaderButton = (
isLoading,
className = "",
disabled = false,
...props ) => (
<Button
className={`LoaderButton ${className}`}
disabled={disabled || isLoading}
{...props}
>
{isLoading && <Glyphicon glyph="refresh" className="spinning" />}
{props.children}
</Button>
)
export default LoaderButton
And the LoaderButton is imported and used here in my Login.js:
export default function Login() {
const history = useHistory();
const { userHasAuthenticated } = useAppContext();
const [isLoading, setIsLoading] = useState(false);
const [fields, handleFieldChange] = useFormFields({
email: "",
password: ""
});
function validateForm() {
return fields.email.length > 0 && fields.password.length > 0;
}
async function handleSubmit(event) {
event.preventDefault();
setIsLoading(true);
try {
await Auth.signIn(fields.email, fields.password);
userHasAuthenticated(true);
history.push("/");
} catch (e) {
onError(e);
setIsLoading(false);
}
}
return (
<div className="Login">
<form onSubmit={handleSubmit}>
<FormGroup controlId="email" bsSize="large">
<ControlLabel>Email</ControlLabel>
<FormControl
autoFocus
type="email"
value={fields.email}
onChange={handleFieldChange}
/>
</FormGroup>
<FormGroup controlId="password" bsSize="large">
<ControlLabel>Password</ControlLabel>
<FormControl
type="password"
value={fields.password}
onChange={handleFieldChange}
/>
</FormGroup>
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={isLoading}
disabled={!validateForm()}
>
Login
</LoaderButton>
</form>
</div>
);
}
The standard functional component works as expected.
But the arrow function component seems to have isLoading stuck to true
AND gets this error:
Warning: Failed prop type: Invalid prop `disabled` of type `object` supplied to `Button`, expected `boolean`.
I thought arrow function components were supposed to be a simpler way to write function components.
I keep thinking it has to do with binding and therefore it's somehow binding the props I have different but I can't find any information on the differences of their bindings. I thought if my Login.js is binding according to the way it's written then I should be fine?
I honestly would prefer to write using an arrow function syntax.

They aren't quite equivalent. You didn't destructure props correctly. Wrap all the props with {} so your functional component is taking a single props argument.
const LoaderButton = ({
isLoading,
className = "",
disabled = false,
...props
}) => (
<Button
className={`LoaderButton ${className}`}
disabled={disabled || isLoading}
{...props}
>
{isLoading && <Glyphicon glyph="refresh" className="spinning" />}
{props.children}
</Button>
);
export default LoaderButton

Related

how do a set a boolean value to false from one react component to main app.js

trying to use the handle submit function to change the isAuthinticated to true from false thats on the main app.js file thats using react router.. all of the redux examples i look at are all using an app js file that has the onclick function on it not react router. thank you if you can help
function App () {
return (
<Router>
<div>
<Switch>
<Route exact path="/" component={Login} />
<Route exact path="/login" component={Login} />
<Route exact path="/signup" component={Signup} />
<PrivateRoute
exact path="/mainpage"
component={MainPage}
isAuthenticated={false}
/>
</Switch>
<Footer />
</div>
</Router>
);
}
export default App;
my login.js that has the click event
const Login = () => {
const history = useHistory()
const [state, setState] = useState({
email: '',
password: ''
});
const [validate, setValid] = useState({
validateEmail: '',
validatePassword: '',
})
const handleInputChange = event => setState({
...state,
[event.target.name]: event.target.value,
})
const handleSubmit = user => {
if(state.password === ''){
setValid({validatePassword:true})
}
if(state.email === '' ){
setValid({validateEmail:true})
}
axios.post(`auth/login`, state )
.then(res => {
console.log(res);
console.log(res.data);
if (res.status === 200 ) {
history.push('/mainpage');
}
})
.catch(function (error) {
console.log(error);
alert('Wrong username or password')
window.location.reload();
});
}
// console.log('state', state)
const {email, password } = state
const [popoverOpen, setPopoverOpen] = useState(false);
const toggle = () => setPopoverOpen(!popoverOpen);
return (
<>
<Container>
<Row>
<Col>
<img src={logo} alt="Logo" id="logo" />
<Button id="Popover1" type="button">
About Crypto-Tracker
</Button>
<Popover placement="bottom" isOpen={popoverOpen} target="Popover1" toggle={toggle}>
<PopoverHeader>About</PopoverHeader>
<PopoverBody>Your personalized finance app to track all potential cryptocurrency investments</PopoverBody>
</Popover>
</Col>
<Col sm="2" id="home" style={{height: 500}}>
<Card body className="login-card">
<Form className="login-form">
<h2 className="text-center">Welcome</h2>
<h3 className="text-center">____________</h3>
<FormGroup>
<Label for="exampleEmail">Email</Label>
<Input invalid={validate.validateEmail} onChange = {handleInputChange} value = {email} type="email" required name="email" placeholder="email" />
<FormFeedback>Please enter email</FormFeedback>
</FormGroup>
<FormGroup>
<Label for="examplePassword">Password</Label>
<Input invalid={validate.validatePassword} onChange = {handleInputChange} value = {password} type="password" required name="password" placeholder="password"/>
<FormFeedback>Please enter password</FormFeedback>
</FormGroup>
<Button onClick={()=> handleSubmit(state)} className="but-lg btn-dark btn-block">Login</Button>
<div className="text-center pt-3"> or sign in with Google account</div>
<Loginbutton />
<div className="text-center">
Sign up
<span className="p-2">|</span>
Forgot password
</div>
</Form>
</Card>
</Col>
</Row>
</Container>
</>
);
}
export default Login;
authslice.js using asyncthunk
import { createAsyncThunk, createSlice } from '#reduxjs/toolkit'
import { userAPI } from '../../../server/routes/authRoutes'
const fetchAuth = createAsyncThunk(
'auth/login',
async (userId, thunkAPI) => {
const response = await userAPI.fetchById(userId)
return response.data
}
)
const authSlice = createSlice({
name: 'isAuthenticated',
initialState: {
value: false,
},
reducers: {
// Authenticated: state => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
// state.value = true;
// },
},
extraReducers: {
[fetchAuth.fulfilled]: state => {
// Add user to the state array
state.value = true
},
[fetchAuth.rejected]: state => {
// Add user to the state array
state.value = false
}
}
});
dispatch(fetchUserById(123))
// export const { increment, decrement, incrementByAmount } = counterSlice.actions;
This would be easy to achieve if you use some kind of global store to store such values. Typical options include Redux, Mobx, etc.
Define your isAuthenticated variable as a global store variable. mutate its value using corresponding package methods like Redux dispatch events or similar from your functions anywhere else in the app.
You can try it using Redux, creating a store to the login variables, and sharing it with the component App.js.

Redirecting the url after login (react js)

I'm a react js beginner. I got stuck in this problem for many days. I don't know how to redirect to path /users when the login is successful (no validation errors). If anything not clear, please tell me. It's my first time to ask question on stackoverflow. Please help :(
//app.js
import React from "react"
import ValidationLog from "./ValidationLog"
import PostList from "./PostList"
import {BrowserRouter as Router,Route,Switch,Redirect} from "react-router-dom"
function App() {
return (
<Router>
<div className="App">
<Switch>
<Route exact path="/" component={ValidationLog}></Route>
<Route path="/users" component={PostList}></Route>
</Switch>
</div>
</Router>
)
}
export default App
//ValidationLog.js
import React from "react"
import {Formik} from "formik"
import * as Yup from "yup"
import {BrowserRouter as Router,Route,Switch,Redirect} from "react-router-dom"
const ValidationLog = () => (
<Formik
initialValues = {{email: "", password: ""}}
onSubmit = {(values,{ setSubmitting}) => {
setTimeout(() => {
<Redirect to="/users" />
}, 500);
}}
validationSchema = {Yup.object().shape({
email: Yup.string()
.email()
.required("Required"),
password: Yup.string()
.required("No password provided")
.min(8,"Password has to be at least 8 characters.")
})
}
>
{props => {
const {
values,
touched,
errors,
isSubmitting,
handleChange,
handleBlur,
handleSubmit
} = props
return (
<div>
<form autoComplete = "off" onSubmit = {handleSubmit}>
<h2 style={{fontSize: 22}}>Login to view our user pool</h2>
<label htmlFor="email">Email:</label>
<input type="text" value={values.email} name="email" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your email" className={errors.email && touched.email && "error"}/>
{errors.email && touched.email && (<div className="input-feedback">{errors.email}</div>)}
<label htmlFor="email">Password:</label>
<input type="password" value={values.password} name="password" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your password" className={errors.password && touched.password && "error"}/>
{errors.password && touched.password && (<div className="input-feedback">{errors.password}</div>)}
<button type="submit" disabled={isSubmitting}>Login</button>
</form>
</div>
)
}}
</Formik>
)
export default ValidationLog
The following is what I tried. I tried to add a <Redirect to /users/> in ValidationLog.js
onSubmit = {(values,{ setSubmitting}) => {
setTimeout(() => {
<Redirect to="/users" />
}, 500);
}}
I also tried to set a variable islogin in ValidationLog.js and import in app.js when there is no validation errors but islogin is always false in app.js.
//ValidationLog.js
export let islogin = false
onSubmit = {(values,{ setSubmitting}) => {
setTimeout(() => {
islogin = true
console.log(`Logged in ${islogin}`)
}, 500);
}}
//app.js
import ValidationLog,{islogin} from "./ValidationLog"
<Route exact path="/">
{islogin ? <Redirect to="/users" /> : null}
</Route>
<Redirect ... /> is a JSX-Construct to create a component at this position. By itself this does not do anything in imperative code-paths like your onSubmit handler.
What you are looking for is an imperative function that you can call outside a React-Tree. Like from the useHistory hook from react-router.
import { useHistory } from "react-router-dom";
...
const history = useHistory();
...
onSubmit={() => history.push("/home")}
More specifically for your example:
const ValidationLog = () => {
const history = useHistory();
return (
<Formik
initialValues = {{email: "", password: ""}}
onSubmit = {(values,{ setSubmitting}) => {
setTimeout(() => {
history.push(...)
}, 500);
}}
...
You can do it using withRouter
Import withRouter from react-router-dom and enclose your component with withRouter in the export.
You can then navigate using this.props.history.push("/newurl")
import React from "react"
import {Formik} from "formik"
import * as Yup from "yup"
// import withRouter
import {BrowserRouter as Router,Route,Switch,Redirect,withRouter} from "react-router-dom"
const ValidationLog = (props) => (
<Formik
initialValues = {{email: "", password: ""}}
onSubmit = {(values,{ setSubmitting}) => {
setTimeout(() => {
// this redirects to /users, make sure you get the import withRouter (check the last export line)
props.history.push("/users");
}, 500);
}}
validationSchema = {Yup.object().shape({
email: Yup.string()
.email()
.required("Required"),
password: Yup.string()
.required("No password provided")
.min(8,"Password has to be at least 8 characters.")
})
}
>
{props => {
const {
values,
touched,
errors,
isSubmitting,
handleChange,
handleBlur,
handleSubmit
} = props
return (
<div>
<form autoComplete = "off" onSubmit = {handleSubmit}>
<h2 style={{fontSize: 22}}>Login to view our user pool</h2>
<label htmlFor="email">Email:</label>
<input type="text" value={values.email} name="email" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your email" className={errors.email && touched.email && "error"}/>
{errors.email && touched.email && (<div className="input-feedback">{errors.email}</div>)}
<label htmlFor="email">Password:</label>
<input type="password" value={values.password} name="password" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your password" className={errors.password && touched.password && "error"}/>
{errors.password && touched.password && (<div className="input-feedback">{errors.password}</div>)}
<button type="submit" disabled={isSubmitting}>Login</button>
</form>
</div>
)
}}
</Formik>
)
// changes
export default withRouter(ValidationLog)
<Redirect> component approach here:
Use a state variable in your component
const [submitted, setSubmitted] = useState(false);
On submitting, if conditions for redirect are met set this state variable to true
setSubmitted(true);
In your component JSX, place the <Redirect to="/users" /> conditionally depending on that state variable
return <Fragment>
{ submitted
? <Redirect to="/users" />
: <MyComponent ...> }
</Fragment>
Note
If you prefer to avoid this ternary operator syntax for whaterver reason, you could solve this with variables in the component logic before the return. Might be cleaner depending on the complexity of the component.

handleSubmit with Formik using TypeScript

I have successfully written a Login component in React using plain Javascript. I would now like to convert this component to TypeScript. I have defined some types and also threw in some "any" just to initially compile. Unfortunately, the onClick parameter in my submit button throws the following error:
TS2322: Type '(e?: FormEvent | undefined) => void' is not assignable to type '(event: MouseEvent<HTMLElement, MouseEvent>)
=> void'.
Here is the relevant code:
class Login extends React.Component<LoginProps, LoginState> {
constructor(props) {
super(props);
this.login = this.login.bind(this);
}
async login(values) {
const user = {
email: values.email,
password: values.password,
};
const query = `mutation userLogin(
$user: UserLoginInputs!
) {
userLogin(
user: $user
) {
token
}
}`;
const data: any = await graphQLFetch(query, { user });
if (data && data.userLogin.token) {
const decoded: any = jwt.decode(data.userLogin.token);
const { onUserChange } = this.props;
onUserChange({ loggedIn: true, givenName: decoded.givenName });
const { history } = this.props;
history.push('/');
}
}
render() {
return (
<Formik
onSubmit={this.login}
validationSchema={loginSchema}
initialValues={{
email: '',
password: '',
}}
>
{({
handleSubmit,
handleChange,
values,
}) => (
<Card>
<Card.Body>
<Form>
<Form.Group>
<Form.Label>E-mail</Form.Label>
<Form.Control
name="email"
value={values.email}
onChange={handleChange}
/>
</Form.Group>
<Form.Group>
<Form.Label>Password</Form.Label>
<Form.Control
name="password"
value={values.password}
onChange={handleChange}
/>
</Form.Group>
</Form>
<Button
type="button"
variant="primary"
onClick={handleSubmit}
>
Submit
</Button>
</Card.Body>
</Card>
)}
</Formik>
);
}
}
I'm new to TypeScript and don't fully understand why an error occurs regarding e versus event when the login function does not explicitly reference either of those. Can someone please help me assign types to my handleSubmit function (aka login)?
I hope that example could help you to resolve your issue
import { Field, Form, Formik } from 'formik';
import * as React from 'react';
import './style.css';
interface MyFormValues {
firstName: string;
}
export default function App() {
const initialValues: MyFormValues = { firstName: '' };
const getSubmitHandler =
() =>
(values, formik) => {
console.log({ values, formik });
alert(JSON.stringify(values, null, 2));
formik.setSubmitting(false);
};
return (
<div>
<Formik
initialValues={initialValues}
onSubmit={getSubmitHandler()}
>
{(formik) => (
<Form>
<label htmlFor="firstName">First Name</label>
<Field id="firstName" name="firstName" placeholder="First Name" />
<button
type="button"
onClick={(event) =>
getSubmitHandler()(formik.values, formik)
}
>
Submit
</button>
</Form>
)}
</Formik>
</div>
);
}

Using React Router to Redirect to next page after successful login

I have created a basic MERN log in page and I am a bit confused on how to redirect the user after a successful log in. I have created a Log in context and when a user successfully logs in I set logged in state to true. I am unsure how I can then redirect to /items route. Any help would be appreciated. Here is my App code:
function App() {
return (
<LoggedInProvider>
<ThemeProvider>
<Switch>
<Route
exact
path="/"
render={() => <SignIn />}
/>
<Route
exact
path="/items"
render={() => <Index />}
/>
</Switch>
</ThemeProvider>
</LoggedInProvider>
);
}
export default App;
Here is my SignIn component:
function Form(props) {
const { isDarkMode } = useContext(ThemeContext);
const { loggedIn, changeLogIn } = useContext(LoggedInContext);
const [isSignUp, setSignUp] = useState(false);
const { classes } = props;
const [usernameValue, setUsernameValue] = useState('');
const [passwordValue, setPasswordValue] = useState('');
const handleUsernameChange = (e) => {
setUsernameValue(e.target.value);
};
const handlePasswordChange = (e) => {
setPasswordValue(e.target.value);
};
// const [value, setValue] = useState(initialVal);
// const handleChange = (e) => {
// setValue(e.target.value);
// };
const handleClick = () => {
setSignUp(!isSignUp);
};
const reset = () => {
setUsernameValue('');
setPasswordValue('');
};
const authSubmitHandler = async (event) => {
event.preventDefault();
if (!isSignUp) {
try {
const response = await fetch('http://localhost:8181/auth', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: usernameValue,
password: passwordValue,
}),
});
const responseData = await response.json();
if (responseData.code === 200) {
console.log('Success Response');
changeLogIn(true);
reset();
}
console.log('This is a response');
console.log(responseData);
} catch (err) {
console.log(err);
}
} else {
try {
const response2 = await fetch('http://localhost:8181/auth', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: usernameValue,
password: passwordValue,
}),
});
const responseData2 = await response2.json();
console.log(responseData2);
} catch (err) {
console.log(err);
}
}
};
return (
<main className={classes.main}>
{!isSignUp ? (
<Paper
className={classes.paper}
style={{ background: isDarkMode ? '#2E3B55' : 'white' }}
>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography variant="h5">Sign In</Typography>
<form
className={classes.form}
onSubmit={authSubmitHandler}
>
<FormControl
margin="normal"
required
fullWidth
>
<InputLabel htmlFor="username">Username</InputLabel>
<Input
id="username1"
name="username1"
value={usernameValue}
onChange={handleUsernameChange}
autoFocus
/>
</FormControl>
<FormControl
margin="normal"
required
fullWidth
>
<InputLabel htmlFor="password">Password</InputLabel>
<Input
id="password"
name="password"
type="password"
value={passwordValue}
onChange={handlePasswordChange}
autoFocus
/>
</FormControl>
<Button
variant="contained"
type="submit"
fullWidth
color="primary"
className={classes.submit}
>
Sign In
</Button>
</form>
<Button
variant="contained"
type="submit"
fullWidth
color="secondary"
className={classes.submit}
onClick={handleClick}
>
Switch to Sign up
</Button>
</Paper>
) : (
<Paper
className={classes.paper}
style={{ background: isDarkMode ? '#2E3B55' : 'white' }}
>
<Avatar className={classes.avatar}>
<LockOutlinedIcon color="primary" />
</Avatar>
<Typography variant="h5">Sign Up</Typography>
<form
className={classes.form}
onSubmit={authSubmitHandler}
>
<FormControl
margin="normal"
required
fullWidth
>
<InputLabel htmlFor="username">Username</InputLabel>
<Input
id="username2"
name="username"
value={usernameValue}
onChange={handleUsernameChange}
autoFocus
/>
</FormControl>
<FormControl
margin="normal"
required
fullWidth
>
<InputLabel htmlFor="password">Password</InputLabel>
<Input
id="password"
name="password"
type="password"
value={passwordValue}
onChange={handlePasswordChange}
autoFocus
/>
</FormControl>
<Button
variant="contained"
type="submit"
fullWidth
color="primary"
className={classes.submit}
>
Sign Up
</Button>
</form>
<Button
variant="contained"
type="submit"
fullWidth
color="secondary"
className={classes.submit}
onClick={handleClick}
>
Switch to Sign In
</Button>
</Paper>
)}
</main>
);
}
// class Form extends Component {
// static contextType = LanguageContext;
// render() {
// return (
// );
// }
// }
export default withStyles(styles)(Form);
And here is my log in context:
import React, { createContext, useState } from 'react';
export const LoggedInContext = createContext();
export function LoggedInProvider(props) {
const [loggedIn, setLoggedIn] = useState(false);
const changeLogIn = (val) => {
setLoggedIn(val);
};
return (
<LoggedInContext.Provider value={{ loggedIn, changeLogIn }}>
{props.children}
</LoggedInContext.Provider>
);
}
In your LoggedInProvider component you can do something like this:
import { useHistory } from "react-router-dom";
import React, { createContext, useState } from "react";
export const LoggedInContext = createContext();
export function LoggedInProvider(props) {
const history = useHistory();
const [loggedIn, setLoggedIn] = useState(false);
const changeLogIn = (val) => {
setLoggedIn(val);
if(val) NavigateAway('/items');
};
const NavigateAway = path => {
history.push(path);
}
return (
<LoggedInContext.Provider value={{ loggedIn, changeLogIn }}>
{props.children}
</LoggedInContext.Provider>
);
}
Hope this work's for you.
Just use props.history.push(). Every route's component will have access to the history object attached to it. As a reference:
const Login = ({ history }) => {
// username, password state fields here
function login(e) {
e.preventDefault();
login({ username, password })
.then(() => {
// set your authentication credentials to some persistent store
history.push('/items');
});
}
return (
// login form markup in here
);
};
well, the easiest way to do is to use the history object available in your props.
Try to see if it exist, you can do the following:
this.props.history.push('/item'): this should redirect you to the page.
Link from react-router-dom: it contains a property called redirect

How to do state operations in function in react without class

this is my React worksection.js file and its function made instead of class
export default function WorkSection() {
now i need to do here constructor to initialise state and do function operations which i'll call on button click
return (
<div className={classes.section}>
<GridContainer justify="center">
<GridItem cs={12} sm={12} md={8}>
<h2 className={classes.title}>Work with us</h2>
<h4 className={classes.description}>
BAIOS BAY LLP is looking for collaborations with you, Contact us
today !
</h4>
<form onSubmit={this.handleSubmit}>
<GridContainer>
<GridItem xs={12} sm={12} md={6}>
<CustomInput
labelText="Your Name"
id="name"
onChange={this.handleChange}
defaultValue={this.state.name}
formControlProps={{
fullWidth: true
}}
/> </GridItem> </GridContainer>
</div>
);
}
this is my form where i am submitting name and will add button click so how can i initialise state and functions to call onclick functions where
my functions are as :
constructor(props) {
super(props);
this.state = {
name : ''}
}
handleChange = event => {
this.setState({
[event.target.id]: event.target.value
});
}
handleClick = event => {
this.setState({
[event.target.id]: event.target.checked
});
}
handleSubmit = event => {
event.preventDefault();
if (this.state.username === '') {
this.showMessage('Info', "Username is empty");
return;
}
}
i need to place this function and i did it with class worksection but how to do it with export default function Worksection()
The thing you're probably looking for called react hooks. They allow you to use state management in your functional components. They're cool because they're lightweight in compare with class components.
First, import useState function from react:
import { useState } from 'react'
Then, before your return, add these lines:
const [name, setName] = useState('');
The first argument here is the name of your state property, and the second one is the function to change it.
So, instead of this:
handleChange = event => {
this.setState({
[event.target.id]: event.target.value
});
}
Write this:
handleChange = event => {
setName(event.target.value);
}
If you want to make it more complex, you can rewrite your hook from this:
const [name, setName] = useState('');
to this:
const [state, setState] = useState({
name: '',
checked: false,
});
export default function WorkSection() {
const { register, handleSubmit } = useForm();
const onSubmit = data => {
axios
.get("
...................... my code ...............
and my input form is :
return (
<div className={classes.section}>
<form onSubmit={handleSubmit(onSubmit)}>
<Input
name="Name"
placeholder="Name"
inputRef={register}
fullWidth={true}
/>
<Input
name="email"
type="email"
placeholder="Email"
fullWidth={true}
inputRef={register({ required: true })}
/>
<Input
name="contact"
placeholder="Contact"
fullWidth={true}
inputRef={register({ required: true })}
/>
<Input
name="description"
placeholder="Message"
multiline={true}
fullWidth={true}
inputRef={register({ required: true })}
/>
<button className="btnColor" justify="center" type="submit">
Send Message
</button>
</GridItem>
</GridContainer>
</form>
</div>
Basically i used
inputRef={register}
and other part as satated above.
Right code , worked for me ~

Categories

Resources