I have a removeUser page where I am using a < Mutation > and then I am doing my error handling using the submitForm() function. This code worked perfectly well:
export default function RemoveUserPage() {
const [isSubmitted, setIsSubmitted] = useState(false);
const [isRemoved ,setIsRemoved] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
function StatusMessage(){
if (isRemoved){
return (
<CustomAlert severity='success' text='User Removed'></CustomAlert>
)
}
//else...
}
function submitForm(RemoveUserMutation: any, email: string) {
setIsSubmitted(true);
RemoveUserMutation({
variables: {
email: email,
},
}).then(({ data }: any) => {
setIsRemoved(true);
})
.catch((error: { message: string; }) => {
setIsRemoved(false);
console.log("Error msg:" + error.message);
setErrorMessage(error.message)
})
}
return (
<Mutation mutation={RemoveUserMutation}
>
{(RemoveUserMutation: any) => (
<div>
<PermanentDrawerLeft></PermanentDrawerLeft>
<Formik
initialValues={{ email: '' }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
validationSchema={schema}
>
{props => {
const {
values: { email },
errors,
touched,
handleChange,
isValid,
setFieldTouched
} = props;
const change = (name: string, e: any) => {
e.persist();
handleChange(e);
setFieldTouched(name, true, false);
};
return (
<div className='main-content'>
<form style={{ width: '100%' }}
onSubmit={e => {e.preventDefault();
submitForm(RemoveUserMutation, email)}}>
<div>
<TextField
variant="outlined"
margin="normal"
id="email"
name="email"
helperText={touched.email ? errors.email : ""}
error={touched.email && Boolean(errors.email)}
label="Email"
value={email}
onChange={change.bind(null, "email")}
/>
<br></br>
<Button
type="submit"
disabled={!isValid || !email}
>
Remove User</Button>
</div>
</form>
<br></br>
{isSubmitted && StatusMessage()}
</div>
)
}}
</Formik>
</div>
)}
</Mutation>
);
}
However, I was suggested to use useMutationinstead. Firstly, I am unable to do so since I get such errors:
Unhandled Rejection (Error): GraphQL error: Variable `email` of type `String!` must not be null.
And even if the mutation works, is there any way I can still modify and use the same function for error handling in my case?
This is what I was trying now but this doesn't work:
export default function RemoveUserPage() {
const [isSubmitted, setIsSubmitted] = useState(false);
const [isRemoved ,setIsRemoved] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
const [removeUser] = useMutation(RemoveUserMutation);
function StatusMessage(){
if (isRemoved){
return (
<CustomAlert severity='success' text='User Removed'></CustomAlert>
)
}
}
function submitForm(RemoveUserMutation: any, email: string) {
setIsSubmitted(true);
RemoveUserMutation({
variables: {
email: email,
},
}).then(({ data }: any) => {
setIsRemoved(true);
})
.catch((error: { message: string; }) => {
setIsRemoved(false);
setErrorMessage(error.message)
})
}
return (
<div>
<PermanentDrawerLeft></PermanentDrawerLeft>
<Formik
initialValues={{ email: '' }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
validationSchema={schema}
>
{props => {
const {
values: { email },
errors,
touched,
handleChange,
isValid,
setFieldTouched
} = props;
const change = (name: string, e: any) => {
e.persist();
handleChange(e);
setFieldTouched(name, true, false);
};
return (
<div className='main-content'>
<form style={{ width: '100%' }}
onSubmit={e => {e.preventDefault();
removeUser({variables: {todo: email }});}}>
<div>
<TextField
variant="outlined"
margin="normal"
id="email"
name="email"
helperText={touched.email ? errors.email : ""}
error={touched.email && Boolean(errors.email)}
label="Email"
value={email}
onChange={change.bind(null, "email")}
/>
<br></br>
<Button
type="submit"
disabled={!isValid || !email}
>
Remove User</Button>
</div>
</form>
<br></br>
{isSubmitted && StatusMessage()}
</div>
)
}}
</Formik>
</div>
);
}
There's no reason to have a RemoveUserMutation anymore -- removeUser is already in the scope, so just use it.
function submitForm(email: string) {
setIsSubmitted(true);
removeUser({
variables: {
email,
},
})
...
}
You can continue to use your submitForm function like this:
onSubmit={e => {
e.preventDefault();
submitForm(email);
}}
This line
removeUser({variables: {todo: email }})
isn't working because there is no todo variable. Since your using TypeScript, you should generate type definitions for your queries and then use them with the hooks. This would prevent mistakes like this.
Related
When I send a post request without an image everything works ok. When I add an image it seems to fall through. I get an Error: Request failed with status code 409. This is the code for my react form page.
const Form = ({ currentId, setCurrentId }) => {
const [postData, setPostData] = useState({
creator: '', title: '', message: '', tags:'', selectedFiles:''
})
const post = useSelector((state) => currentId ? state.posts.find((p) => p._id === currentId) : null);
const classes = useStyles();
const dispatch = useDispatch();
useEffect(() => {
if(post) setPostData(post);
}, [post])
const handleSubmit = (e) => {
e.preventDefault();
if(currentId) {
dispatch(updatePost(currentId, postData));
} else {
dispatch(createPost(postData));
}
//clear();
}
const clear = () => {
setCurrentId(0);
setPostData({creator: '', title: '', message: '', tags:'', selectedFiles:''})
}
return (
<Paper className={classes.paper}>
<form autoComplete='off' noValidate className={`${classes.root}${classes.form}`} onSubmit={handleSubmit}>
<Typography variant='h6'>{currentId ? 'Editing' : 'Creating' } a Store</Typography>
<TextField name='creator' variant='outlined' label='Creator' fullWidth value={postData.creator}onChange={(e) => setPostData({ ...postData, creator: e.target.value })}/>
<TextField
name='Store Name'
variant='outlined'
label='name'
fullWidth
value={postData.title}
onChange={(e) => setPostData({ ...postData, title: e.target.value })}
/>
<TextField
name='message'
variant='outlined'
label='message'
fullWidth
value={postData.message}
onChange={(e) => setPostData({ ...postData, message: e.target.value })}
/>
<TextField
name='crypto'
variant='outlined'
label='crypto'
fullWidth
value={postData.tags}
onChange={(e) => setPostData({ ...postData, tags: e.target.value })}
/>
<div className={classes.fileInput}>
<FileBase
type='file'
multiple={false}
onDone={(base64) => setPostData({ ...postData, selectedFile: base64})}
/>
</div>
<Button className={classes.buttonSubmit} variant="container" color="primary" size="large" type="submit" fullwidth>Submit</Button>
<Button variant="contained" color="secondary" size="small" onClick={clear} fullwidth>Clear</Button>
</form>
</Paper>
);
}
export default Form;
This is the function for my server side route. WHere I take the form info and post it to the server.
export const createPost = async (req, res) => {
const { title, message, selectedFile, creator, tags } = req.body;
const newPostMessage = new PostMessage({ title, message, selectedFile, creator, tags })
try {
await newPostMessage.save();
res.status(201).json(newPostMessage );
} catch (error) {
res.status(409).json({ message: error.message });
}
}
This is my model for mongodb.
import mongoose from 'mongoose';
const postSchema = mongoose.Schema({
title: String,
message: String,
creator: String,
tags: [String],
selectedFile: String,
likeCount: {
type: Number,
default: 0
},
createdAt: {
type: Date,
default: new Date()
},
})
const PostMessage = mongoose.model('PostMessage', postSchema);
export default PostMessage;
Your Mongo model has selectedFile declared as a String. Your frontend is sending a base64-encoded jpeg file, which Mongo doesn't know how to convert into a String.
Check out this question for some leads on storing jpegs in Mongo.
In my case, the problem was on this line:
<FileBase
type='file'
multiple={false}
onDone={(base64) => setPostData({ ...postData, selectedFile: base64})}
/>
the solution :
<FileBase
type="file"
multiple={false}
onDone={({ base64 }) =>
setPostData({ ...postData, selectedFile: base64 })
}
/>
The only difference is the {}.
I am trying to write a test to for my component which uses the Material UI Autocomplete component. I am not sure what I am doing wrong but my test doesn't seem to be triggering the onChange of the Material UI Autocomplete component.
it('should render autocomplete and select a user', async () => {
searchContact.mockResolvedValueOnce({
data: {
value: [
{
displayName: 'Jan Travis',
userPrincipalName: 'JanT#email.uk',
},
{
displayName: 'Jon Test',
userPrincipalName: '',
},
{
displayName: 'Jay Test',
userPrincipalName: 'JayT#email.uk',
},
],
},
});
initialProps.activityName = 'some-activity';
initialProps.testId = 'contact-person[0]';
initialProps.fromType = 'planning-contact-person';
const { getByRole } = render(<AutoCompleteUserSearch {...initialProps} />);
const autocomplete = getByRole('textbox');
autocomplete.focus();
await act(async () => {
fireEvent.change(document.activeElement, { target: { value: 'Jay' } });
});
fireEvent.keyDown(document.activeElement, { key: 'ArrowDown' });
fireEvent.keyDown(document.activeElement, { key: 'Enter' });
await waitFor(() => {
expect(autocomplete.value).toEqual('Jay');
});
Here is what my autocomplete component looks like
return (
<React.Fragment>
<Autocomplete
id={props.activityName ? props.activityName : props.id}
freeSolo
data-testid={props.testId ? props.testId : 'autocomplete'}
defaultValue=""
getOptionLabel={(option) => (typeof option === 'string' ? option : option.displayName)}
getOptionSelected={(option, value) => {
return option.displayName === value;
}}
filterOptions={(x) => x}
open={open}
onOpen={() => {
setOpen(true);
}}
onClose={() => {
setOpen(false);
}}
value={autoCompleteValue}
autoComplete
includeInputInList
options={[...autoCompleteOptions]}
filterSelectedOptions
clearOnEscape
onChange={(event, newValue, reason) => {
setAutoCompleteOptions(newValue ? [newValue, ...autoCompleteOptions] : autoCompleteOptions);
if (newValue) {
setAutoCompleteValue(newValue.displayName);
if (newValue.userPrincipalName) {
setSelectUserEmailAddress(newValue.userPrincipalName);
setUserEmailAddressError();
} else {
setUserEmailAddressError('This user does not have an email address');
}
}
if (reason === 'clear') {
setAutoCompleteValue('');
}
}}
size="small"
renderInput={(params) => (
<div ref={params.InputProps.ref}>
<Input
type="text"
label="Search user"
name={props.activityName ? props.activityName : props.name}
{...params.inputProps}
inputProps={{ 'aria-label': 'Search user' }}
onChange={(ev) => {
onChangeHandle(ev.target.value);
}}
/>
</div>
)}
renderOption={(option, { inputValue }) => {
const matches = match(option.displayName, inputValue);
const parts = parse(option.displayName, matches);
return (
<div>
{parts.map((part, index) => (
<span key={index} style={{ fontWeight: part.highlight ? 700 : 400 }}>
{part.text}
</span>
))}
</div>
);
}}
/>
The onChange within the autocomplete doesn't seem to be trigged. Not sure if the within the test the keyDown is working properly.
Here is my onChangeHandle function within the Input onChange, which is being called
const onChangeHandle = (e) => {
setAutoCompleteValue(e);
if (e !== '') {
if (e) {
searchContact(e)
.then((res) => {
setAutoCompleteOptions(res.data.value);
})
.catch(() => {});
}
}
};
Any help would be appreciated, thanks.
<-- Whenever I try to update user info,I am not getting the updated values.But when I reload the page,I get the updated values.Is there a way to get the updated values whenever I hit the update button which is in MiddlePanel? Right now I am fetching all users in loadUsers. -->
class Home extends Component {
state = {
loadUsers: [],
currentUser: null,
};
async componentDidMount() {
const res = await axios.get("http://localhost:5000/users");
this.setState({ loadUsers: res.data });
}
setUser = (currentUser) => {
this.setState({ currentUser });
};
render() {
return (
<Fragment>
<div className="row">
<div className="col-md-3" style={{ backgroundColor: "#303F9F" }}>
<Typography variant="h6">List all Counsellors</Typography>
{this.state.loadUsers.map((user) => {
const { _id, firstname, lastname } = user;
return (
<div key={_id}>
<PrimaryButton
onClick={(e) => {
this.setUser(user);
}}
>
{firstname} {lastname}
</PrimaryButton>
</div>
);
})}
</div>
<div className="col-md-4">
{this.state.currentUser && (
<div>
<MiddlePanel user={this.state.currentUser} />
</div>
)}
</div>
</div>
</Fragment>
);
}
}
export default Home;
Here is my middlepanel code
const MiddlePanel = ({ user }) => {
const [data, setData] = useState({
firstname: "",
lastname: "",
email: "",
phoneNo: "",
});
const { firstname, lastname, email, phoneNo } = data;
useEffect(() => {
const fetchUser = async () => {
const res = await axios.get(`http://localhost:5000/users/${user._id}`);
setData({
firstname: res.data.firstname,
lastname: res.data.lastname,
email: res.data.email,
phoneNo: res.data.phoneNo,
});
};
fetchUser();
}, [user._id]);
const handleChange = (e) => {
const { name, value } = e.target;
setData({ ...data, [name]: value });
};
const handleSubmit = async (e) => {
e.preventDefault();
const newUser = { firstname, lastname, email, phoneNo };
try {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify(newUser);
await axios.patch(
`http://localhost:5000/users/${user._id}`,
body,
config
);
} catch (err) {
console.log(err);
}
};
return (
<div>
<Form onSubmit={handleSubmit}>
<Input
type="text"
name="firstname"
onChange={handleChange}
value={data.firstname}
/>
<Input
type="text"
name="lastname"
onChange={handleChange}
value={data.lastname}
/>
<Input
type="email"
name="email"
onChange={handleChange}
value={data.email}
/>
<Input
type="tel"
name="phoneNo"
onChange={handleChange}
value={data.phoneNo}
/>
<PrimaryButton>Update</PrimaryButton>
</Form>
</div>
);
};
I want to display the updated user info which I am doing in the Middlepanel
try this code , I tested this in codesandbox it works
import React, { Component, Fragment } from "react";
import axios from "axios";
class Home extends Component {
state = {
loadUsers: [],
currentUser: null
};
async componentDidMount() {
const res = await axios.get("https://reqres.in/api/users?page=2");
this.setState({ loadUsers: res.data.data });
}
setUser = (currentUser) => {
console.log(currentUser);
this.setState({ currentUser });
};
render() {
return (
<Fragment>
<div className="row">
<div className="col-md-3" style={{ backgroundColor: "#303F9F" }}>
{/* <Typography variant="h6">List all Counsellors</Typography> */}
{this.state.loadUsers
? this.state.loadUsers.map((user) => {
const { _id, first_name, lastname } = user;
return (
<div key={_id}>
<button onClick={()=> this.setUser(first_name)}>
{first_name} {lastname}
</button>
</div>
);
})
: null}
</div>
<div className="col-md-4">
{this.state.currentUser && <div>{this.state.currentUser}</div>}
</div>
</div>
</Fragment>
);
}
}
export default Home;
I am getting the error
Error: Function components cannot have refs. Did you mean to use
React.forwardRef()?
And if you check my code it is correct. I am also passing even and it says
Line 91: Unexpected use of 'event' no-restricted-globals
If I am doing something wrong I do not know. According to my research I found that there is some version issue maybe or not. I am using the latest version of create react app
import React, { Component } from 'react';
import { AuthUserContext } from '../Session';
import { withFirebase } from '../Firebase';
import NewsList from './NewsList';
import { ValidatorForm, TextValidator } from 'react-material-ui-form-validator';
import { Container, Card, CardContent, Button } from '#material-ui/core';
import Form from 'react-bootstrap/Form';
class News extends Component {
constructor(props) {
super(props);
this.state = {
newsTitle: '',
newsDescription: '',
news: [],
limit: 5,
loading: false,
submitted: false,
error: null,
};
}
componentDidMount() {
this.onListenForNews();
}
onListenForNews = () => {
this.setState({ loading: true });
this.props.firebase
.news()
.orderByChild('createdAt')
.limitToLast(this.state.limit)
.on('value', snapshot => {
const newsObject = snapshot.val();
if (newsObject) {
const newsLis = Object.keys(newsObject).map(key => ({
...newsObject[key],
uid: key,
}));
this.setState({
news: newsLis,
loading: false,
});
} else {
this.setState({ news: null, loading: false });
}
});
};
componentWillUnmount() {
this.props.firebase.news().off();
}
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
onCreateNews = (event, authUser) => {
this.props.firebase.news().push({
newsTitle: this.state.newsTitle,
newsDescription: this.state.newsDescription,
userId: authUser.uid,
createdAt: this.props.firebase.serverValue.TIMESTAMP,
});
this.setState({
newsTitle: '',
newsDescription: '',
error: null,
submitted: true,
});
event.preventDefault();
};
onEditNews = (news, newsTitle, newsDescription) => {
this.props.firebase.news(news.uid).set({
...news,
newsTitle,
newsDescription,
editedAt: this.props.firebase.serverValue.TIMESTAMP,
});
};
onRemoveNews = uid => {
this.props.firebase.news(uid).remove();
};
onNextPage = () => {
this.setState(
state => ({ limit: state.limit + 5 }),
this.onListenForNews,
);
};
render() {
const { users } = this.props;
const { newsTitle, newsDescription, news, loading, submitted, error } = this.state;
return (
<AuthUserContext.Consumer>
{authUser => (
<div>
{!loading && news && (
<button type="button" onClick={this.onNextPage}>
More
</button>
)}
{loading && <div>Loading ...</div>}
{news && (
<NewsList
news={news.map(news => ({
...news,
user: users
? users[news.userId]
: { userId: news.userId },
}))}
onEditNews={this.onEditNews}
onRemoveNews={this.onRemoveNews}
/>
)}
{!news && <div>There are no messages ...</div>}
<Container maxWidth="lg">
<ValidatorForm
ref="form"
onSubmit={event =>
this.onCreateNews(event, authUser)
}
>
<div>
{error && (
<div className="alert alert-danger" role="alert">
{error.message}
</div>
)}
<Card>
<CardContent>
<Form.Group>
<TextValidator
label="News Title"
onChange={this.handleChange}
name="newsTitle"
type="text"
value={newsTitle}
variant="outlined"
fullWidth={true}
validators={['required']}
errorMessages={['New title field is required', 'News title is not valid']}
/>
</Form.Group>
<Form.Group>
<TextValidator
label="Description"
onChange={this.handleChange}
name="newsDescription"
type="text"
value={newsDescription}
variant="outlined"
fullWidth={true}
validators={['required']}
errorMessages={['Description field is required']}
/>
</Form.Group>
<Form.Group>
<Button
color="primary"
variant="contained"
type="submit"
fullWidth={true}
size="large"
disabled={submitted}
>
{
(submitted && 'Signing In - Redirecting')
|| (!submitted && 'Sign In')
}
</Button>
</Form.Group>
</CardContent>
</Card>
</div>
</ValidatorForm>
</Container>
</div>
)}
</AuthUserContext.Consumer>
);
}
}
export default withFirebase(News);
So, I am trying to add some data to two different array in react typescript
const [deviceNames, setDeviceNames] = useState<Array<string>>([])
const [serialNumbers, setSerialNumbers] = useState<Array<string>>([])
I am now looping over both the array here and displaying the content
{deviceNames.length > 0 &&
serialNumbers.length > 0 &&
deviceNames.map(deviceName => {
return serialNumbers.map(serialNumber => {
return (
<CardDevice
deviceName={deviceName}
serialNumber={serialNumber}
/>
)
})
})}
I am adding data to these array by clicking on a button and then showing modal and then like this
onSubmit = (values: any) => {
clearError()
setAddDevice(false)
setDeviceNames(deviceName => [...deviceName, values.deviceName])
setSerialNumbers(serialNumber => [...serialNumber, values.serialNumber])
}
I am using react hook form.
So what i want is whenever i loop over both the arrays, each time it should display the content which was just added in the array the new one not the last one again which was already added and displayed. I hope i am able to make some point here. It does the job but whenever user enters new device after adding one, it add the old one again and then the new one and then again and then again same thing.
i just want to display just one new item which was just last added to an array by the user.
Thanks
Basically i answered my own question:
import React, { useState } from "react";
function App() {
const [addCardData, setAddCardData] = useState("");
const [addCards, setAddCards] = useState<Array<string>>([]);
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setAddCardData(event.target.value);
};
const handleSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
event.preventDefault();
setAddCards(prevState => [...prevState, addCardData]);
};
return (
<div
className="App"
style={{ textAlign: "center", margin: "0 auto", marginTop: "10em" }}
>
<form onSubmit={handleSubmit}>
<input type="text" onChange={handleChange} placeholder="Add any text" />
<button type="submit">Add</button>
</form>
{addCards.map(addCard => (
<h3>{addCard}</h3>
))}
</div>
);
}
export default App;
Here is some more Dynamic Approach:
import React, { useState } from "react";
import { TextInput } from "./components/TextInput";
interface Device {
deviceName: string;
serialNumber: string | number;
}
const App: React.FC = () => {
const [deviceName, setDeviceName] = useState("");
const [serialNumber, setSerialNumber] = useState("");
const [deviceInfos, setDeviceInfos] = useState<Device[]>([]);
const handleDeviceChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setDeviceName(event.target.value);
};
const handleSerialChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setSerialNumber(event.target.value);
};
const handleSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
event.preventDefault();
addDevice();
setDeviceName("");
setSerialNumber("");
};
const addDevice = () => {
const newDevice: Device[] = [
...deviceInfos,
{ deviceName: deviceName, serialNumber: serialNumber }
];
setDeviceInfos(newDevice);
};
return (
<div
className="App"
style={{ textAlign: "center", margin: "0 auto", marginTop: "10em" }}
>
<form onSubmit={handleSubmit}>
<TextInput
type="text"
placeholder="Add Device Name"
handleChange={handleDeviceChange}
value={deviceName}
/>
<TextInput
type="text"
placeholder="Add fuck"
handleChange={handleSerialChange}
value={serialNumber}
/>
<button type="submit">Add</button>
</form>
{deviceInfos.map((device, i) => (
<div key={i}>
<h3>{device.deviceName}</h3>
<h3>{device.serialNumber}</h3>
</div>
))}
</div>
);
};
export default App;
Much Better Approach i used in the production
const ProfileDevices: React.FC<Props> = ({ onSubmit }) => {
const [addDevice, setAddDevice] = useState(false)
const [deviceInfos, setDeviceInfos] = useState<Device[]>([])
const { register, handleSubmit, errors, clearError } = useForm({
mode: 'onSubmit',
})
const addDevices: any = () => {
setAddDevice(true)
}
onSubmit = (values: any) => {
clearError()
setAddDevice(false)
const newDevice: Device[] = [
...deviceInfos,
{ deviceName: values.deviceName, serialNumber: values.serialNumber },
]
setDeviceInfos(newDevice)
}
return (
<ProfileContentContainer>
<ProfileHeader>
<ProfileTitle>Devices</ProfileTitle>
<ProfileActions>
<Button
type="button"
bgType="fill"
size="default"
label="Add Device"
onClick={addDevices}
/>
</ProfileActions>
</ProfileHeader>
{console.log(deviceInfos)}
<DeviceList>
<CardDevice deviceName="Device Name" serialNumber="QR10001123456788" />
<CardDevice deviceName="Device Name" serialNumber="QR10001123456789" />
{deviceInfos.map((device, i) => (
<CardDevice
key={i}
deviceName={device.deviceName}
serialNumber={device.serialNumber}
/>
))}
</DeviceList>
<Modal isActive={addDevice} toggleModal={() => setAddDevice(false)}>
<ModalContent>
<ModalHeader title="Add Device" />
<AuthForm
onSubmit={handleSubmit(onSubmit)}
className="modalAddDeviceForm"
>
<InputText
placeholder="DeviceName"
name="deviceName"
type="text"
register={register({ required: true, maxLength: 10 })}
hasError={errors.deviceName}
errorMessage={
errors.serialNumber ? errors.serialNumber.message : undefined
}
/>
<InputText
placeholder="Serial Number"
name="serialNumber"
type="text"
register={register({ required: true, maxLength: 10 })}
hasError={errors.serialNumber}
errorMessage={
errors.serialNumber ? errors.serialNumber.message : undefined
}
/>
<Button type="submit" bgType="fill" size="default" label="Add" />
</AuthForm>
<ModalActions></ModalActions>
</ModalContent>
</Modal>
</ProfileContentContainer>
)
}
export default ProfileDevices